上一篇
安卓向服务器发送图片
- 行业动态
- 2025-04-24
- 2
安卓通过HTTP POST请求,使用OkHttp/Retrofit等库,将图片文件或Base64编码后的数据发送至服务器
权限配置
安卓应用需要申请以下权限才能访问本地图片并执行网络请求:
权限类型 | 用途 | 声明方式(AndroidManifest.xml) |
---|---|---|
存储权限 | 读取本地图片 | <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> |
存储权限 | 写入临时文件(Android 10+) | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
网络权限 | 发送网络请求 | <uses-permission android:name="android.permission.INTERNET"/> |
注意:Android 6.0+ 需动态申请存储权限,Android 10+ 建议使用 MediaStore
或 Scoped Storage
模式。
图片选择与预处理
从本地选择图片
通过 Intent
调用系统相册选择图片:
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE);
获取图片真实路径
// 处理返回的 URI Uri imageUri = data.getData(); String path = getPathFromUri(imageUri); // 需实现该方法,通过 ContentResolver 解析路径
图片压缩(防止内存溢出)
Bitmap bitmap = BitmapFactory.decodeFile(path); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); // 压缩为 JPEG,质量 80% byte[] imageBytes = baos.toByteArray();
发送图片到服务器
使用 OkHttp 构建 Multipart 请求
OkHttpClient client = new OkHttpClient(); MultipartBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("image", "image.jpg", RequestBody.create(imageBytes, MediaType.parse("image/jpeg"))) .build(); Request request = new Request.Builder() .url("https://yourserver.com/upload") // 替换为实际服务器地址 .post(body) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 处理失败(如网络错误) } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { // 处理成功(如关闭加载框) } } });
添加额外参数(如用户 ID)
.addFormDataPart("userId", "12345") // 添加文本参数
关键问题处理
问题场景 | 解决方案 |
---|---|
Android 10+ 存储权限限制 | 使用 MediaStore.download() 获取临时文件路径,或通过 ContentResolver 直接读取流 |
大图片导致 OOM | 使用 BitmapFactory.Options 设置 inSampleSize 进行采样压缩 |
上传进度显示 | 自定义 RequestBody 包装图片数据,在 writeTo() 方法中计算进度 |
完整流程示例代码
// 1. 选择图片 Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE); // 2. 处理选中的图片 @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 uri = data.getData(); String path = getPathFromUri(uri); // 实现路径解析逻辑 // 压缩并上传图片... } }
相关问题与解答
问题1:如何支持多张图片批量上传?
解答:将图片文件放入 List
,循环构建多个 MultipartBody.Part
,或使用 MultipartBody.Builder
追加多个 addFormDataPart
,注意控制并发数以避免内存溢出。
问题2:如何优化大文件上传的稳定性?
解答:
- 分片上传:将图片分割为多个小块(如每块 1MB),逐块上传并拼接。
- 断点续传:记录已上传的字节偏移量,网络中断后从断点继续上传。
- 后台服务:使用
WorkManager
或Service
确保上传任务在应用退出后继续