当前位置:首页 > 行业动态 > 正文

安卓向服务器发送图片

安卓通过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+ 建议使用 MediaStoreScoped 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:如何优化大文件上传的稳定性?

解答

  1. 分片上传:将图片分割为多个小块(如每块 1MB),逐块上传并拼接。
  2. 断点续传:记录已上传的字节偏移量,网络中断后从断点继续上传。
  3. 后台服务:使用 WorkManagerService 确保上传任务在应用退出后继续
0