上一篇
安卓上传图片到php服务器
- 行业动态
- 2025-04-24
- 4809
安卓用MultipartEntity上传图片,PHP服务器端通过$_FILES接收,move_uploaded_file保存至指定目录,需配置服务器写入权限并校验文件
安卓端实现图片上传
权限配置
在 AndroidManifest.xml
中添加存储和网络权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/>
选择图片
通过 Intent
调用系统相册或相机:
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE);
处理选中的图片
在 onActivityResult
中获取图片路径并转换为 File
:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_SELECT_IMAGE && resultCode == RESULT_OK) { Uri imageUri = data.getData(); File file = new File(getPathFromUri(imageUri)); // 需实现 getPathFromUri 方法 uploadImage(file); } }
上传图片到服务器
使用 Retrofit
或 OkHttp
发送 Multipart 请求:
// 示例:使用 Retrofit 上传 public interface ApiService { @Multipart @POST("upload.php") Call<ResponseBody> uploadImage(@Part MultipartBody.Part image); } private void uploadImage(File file) { Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://yourserver.com/") // 替换为你的服务器地址 .build(); ApiService apiService = retrofit.create(ApiService.class); MultipartBody.Part imagePart = MultipartBody.Part.createFormData("image", file.getName(), RequestBody.create(file, MediaType.parse("image/"))); apiService.uploadImage(imagePart).enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { // 上传成功 } else { // 处理错误(如服务器返回错误码) } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 网络错误处理 } }); }
PHP服务器端接收图片
创建上传脚本 upload.php
<?php $targetDir = "uploads/"; // 保存目录 $targetFile = $targetDir . basename($_FILES["image"]["name"]); $imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION)); // 检查文件类型是否合法 $allowedTypes = array("jpg", "jpeg", "png", "gif"); if (!in_array($imageFileType, $allowedTypes)) { echo json_encode(["status" => "error", "message" => "Invalid file type"]); exit; } // 检查文件大小(例如限制为 5MB) if ($_FILES["image"]["size"] > 5 1024 1024) { echo json_encode(["status" => "error", "message" => "File too large"]); exit; } // 移动文件到目标目录 if (!move_uploaded_file($_FILES["image"]["tmp_name"], $targetFile)) { echo json_encode(["status" => "error", "message" => "Upload failed"]); exit; } echo json_encode(["status" => "success", "url" => $targetFile]); ?>
关键步骤与代码对照表
步骤 | 安卓端实现 | PHP服务器端实现 |
---|---|---|
选择图片 | 使用 Intent.ACTION_PICK 调用系统相册 | 无需处理 |
权限配置 | 在 AndroidManifest.xml 中声明 READ_EXTERNAL_STORAGE 和 INTERNET | 无需配置(PHP默认有文件读写权限) |
图片转换为文件 | 通过 Uri 获取文件路径并创建 File 对象 | 无需处理 |
发送网络请求 | 使用 Retrofit 或 OkHttp 发送 Multipart 请求 | 通过 $_FILES 接收文件 |
服务器端保存文件 | 无需处理 | 使用 move_uploaded_file 将临时文件移动到目标目录 |
错误处理 | 检查响应码、捕获异常 | 检查文件类型、大小,返回 JSON 格式的错误信息 |
常见问题与解决方法
问题 | 解决方法 |
---|---|
安卓端崩溃:未获取存储权限 | 在运行时动态申请权限(Android 6.0+):ActivityCompat.requestPermissions |
服务器端无法保存文件 | 检查 uploads/ 目录是否存在且有写入权限 |
上传大文件失败 | 修改 PHP 配置文件 php.ini 中的 upload_max_filesize 和 post_max_size |
图片显示为空白 | 确保服务器返回的路径正确,且图片 URL 可访问(如使用绝对路径) |
相关问题与解答
问题1:如何实现多张图片批量上传?
解答:
在安卓端,可以通过循环遍历选中的图片列表,逐个添加到 MultipartBody
中。
List<File> files = ...; // 获取多张图片的File对象 for (File file : files) { MultipartBody.Part part = MultipartBody.Part.createFormData("images[]", file.getName(), RequestBody.create(file, MediaType.parse("image/"))); parts.add(part); // 将每个文件添加到请求体中 }
服务器端需修改 upload.php
,通过 $_FILES["images"][
name]
循环处理多个文件。
问题2:如何限制上传图片的分辨率?
解答:
在安卓端上传前,可以使用 Bitmap
压缩图片:
Bitmap bitmap = BitmapFactory.decodeFile(filePath); Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 800, 800, true); // 限制最大宽高为800px File scaledFile = saveBitmapToFile(scaledBitmap); // 自定义方法,将Bitmap保存为File
或在服务器端使用 PHP 的 imagecopyresampled
函数调整图片