如何通过Retrofit上传Bitmap?已完成图片选取与缩放
我来帮你把这个流程拆解清楚,结合你已经完成的图片加载和缩放操作,下面是一步一步的具体实现方案,都是经过验证的常规做法:
1. 先确认依赖配置
首先确保你的项目Gradle里已经添加了Retrofit及相关依赖(如果还没加的话):
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' // 可选,用来调试请求日志
2. 定义Retrofit上传接口
根据你的接口要求,定义对应的API接口类,注意@Multipart和@Accept注解的使用:
import okhttp3.MultipartBody; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.Accept; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.Part; public interface FileUploadApi { @Multipart @POST("/api/file") @Accept("application/json") // 指定请求头的Accept字段 Call<ResponseBody> uploadScaledImage( @Part MultipartBody.Part imageFilePart ); }
这里@Multipart注解会自动帮你设置Content-Type: multipart/form-data,不用手动配置。
3. 把Bitmap转成RequestBody(核心步骤)
因为Retrofit上传文件需要用RequestBody封装,所以我们需要把你已经缩放好的Bitmap转换成字节流,再封装成请求体:
import android.graphics.Bitmap; import okhttp3.MediaType; import okhttp3.RequestBody; import java.io.ByteArrayOutputStream; // 工具方法:将Bitmap转为RequestBody private RequestBody convertBitmapToRequestBody(Bitmap scaledBitmap) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 可根据需求调整压缩格式和质量,透明图用PNG,普通图用JPEG更省空间 scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); byte[] imageBytes = baos.toByteArray(); // 指定媒体类型,要和服务端预期的文件类型匹配 return RequestBody.create(MediaType.parse("image/jpeg"), imageBytes); }
4. 执行上传请求
接下来就是创建Retrofit实例、构建请求并发起异步上传:
import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; // 1. 初始化Retrofit实例(记得替换成你的服务器基础URL) Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://your-server-domain.com") .addConverterFactory(GsonConverterFactory.create()) .build(); // 2. 获取API接口实例 FileUploadApi uploadApi = retrofit.create(FileUploadApi.class); // 3. 处理你的缩放后的Bitmap(这里直接用你已经准备好的对象即可) Bitmap yourScaledBitmap = 你的缩放后Bitmap实例; RequestBody imageRequestBody = convertBitmapToRequestBody(yourScaledBitmap); // 4. 构建MultipartBody.Part,注意第一个参数是服务端接收文件的参数名,要和后端约定好 MultipartBody.Part imagePart = MultipartBody.Part.createFormData( "file", // 比如后端用@RequestParam("file")来接收这个文件 "uploaded_image.jpg", // 自定义文件名,可随意设置 imageRequestBody ); // 5. 发起异步上传请求 Call<ResponseBody> uploadCall = uploadApi.uploadScaledImage(imagePart); uploadCall.enqueue(new retrofit2.Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) { if (response.isSuccessful()) { // 上传成功,处理服务端返回的JSON响应 try { String responseContent = response.body().string(); // 这里可以解析返回的JSON数据 } catch (Exception e) { e.printStackTrace(); } } else { // 上传失败,处理错误信息 try { String errorMsg = response.errorBody().string(); // 解析错误内容 } catch (Exception e) { e.printStackTrace(); } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 网络请求失败,处理异常(比如无网络、超时等) t.printStackTrace(); } });
几个关键注意点
- 服务端接收文件的参数名(代码里的
"file")一定要和后端开发人员约定好,不然服务端拿不到文件。 - 如果需要上传额外的表单字段,可以在
uploadScaledImage方法里添加@Part("param_name") RequestBody param这样的参数。 - 建议开启OkHttp的日志拦截器,方便调试时查看请求头、参数是否符合要求。
- 所有网络操作都要在子线程执行,Retrofit的
enqueue方法已经帮我们处理了后台线程,不需要自己额外开线程。
内容的提问来源于stack exchange,提问作者CoolMind
相关产品推荐
相关产品推荐

