上一篇
安卓中图片上传到服务器
- 行业动态
- 2025-04-24
- 5
安卓图片上传需先获取图片路径或Bitmap,压缩后转为Base64或Multipart格式,通过OkHttp/Retrofit等库在子线程发起POST请求,需声明存储和网络权限,注意处理异常及进度
安卓图片上传到服务器实现步骤
权限配置
存储权限(读取/写入本地文件)
- 在
AndroidManifest.xml
中声明:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- Android 6.0+ 需动态申请权限:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); }
- 在
网络权限
- 在
AndroidManifest.xml
中声明:<uses-permission android:name="android.permission.INTERNET"/>
- 在
获取图片
方式 | 实现方法 | 说明 |
---|---|---|
从相册选择 | Intent.createChooser(Intent.ACTION_GET_CONTENT, "选择图片") | URI获取图片 |
拍照获取 | MediaStore.ACTION_IMAGE_CAPTURE | 需指定文件路径保存照片 |
从文件选择 | 通过文件管理器或第三方库(如 FilePicker ) | 直接获取文件路径 |
示例代码(从相册选择):
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/"); startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE);
图片处理
压缩图片(减少体积)
- 使用
BitmapFactory.Options
采样压缩:BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; // 宽高缩小为1/4 Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
- 或使用第三方库(如 Luban):
Luban.with(this) .load(filePath) .setCompressListener(new OnCompressListener() { @Override public void onStart() {} @Override public void onSuccess(File file) { // 压缩后的文件 } @Override public void onError(Throwable e) {} }).launch();
- 使用
转换为 Base64(可选)
- 将图片转为字符串上传:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); String base64 = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
- 将图片转为字符串上传:
上传图片
使用 Retrofit + OkHttp 实现:
依赖配置
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
定义 API 接口
public interface ApiService { @Multipart @POST("upload/image") Call<ResponseBody> uploadImage(@Part MultipartBody.Part image); }
创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://yourserver.com/") // 替换为服务器地址 .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService apiService = retrofit.create(ApiService.class);
构建请求体并上传
File file = new File(imagePath); // 本地图片路径 RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), file); MultipartBody.Part part = MultipartBody.Part.createFormData("image", file.getName(), requestBody); apiService.uploadImage(part).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) { // 网络错误处理 } });
进度监听与错误处理
添加上传进度监听
- 自定义
Interceptor
或使用ProgressRequestBody
:OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(chain -> { Response originalResponse = chain.proceed(chain.request()); // 获取响应并计算进度 return originalResponse; }) .build();
- 自定义
错误处理
- 网络异常:检查设备网络状态,提示重试。
- 服务器错误:根据
response.code()
处理(如 404/500)。 - 文件过大:压缩图片或分片上传。
相关问题与解答
问题1:上传时提示“权限被拒绝”
解答:
- 检查是否在
AndroidManifest.xml
中声明了WRITE_EXTERNAL_STORAGE
和INTERNET
权限。 - Android 6.0+ 需动态申请存储权限:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); }
- 确保用户已授权,否则无法访问本地文件。
问题2:上传失败,服务器返回“400 Bad Request”
解答:
可能原因1:文件格式不符合要求
- 检查服务器是否限制图片格式(如仅支持 JPEG/PNG)。
- 确保
MediaType
正确设置:MediaType.parse("image/jpeg")
。
可能原因2:缺少必要参数
- 服务器可能要求额外字段(如
token
或fileName
)。 - 在
MultipartBody.Part
中添加参数:MultipartBody.Part part = MultipartBody.Part.createFormData("image", file.getName(), requestBody) .addField("token", "your_token_value");
- 服务器可能要求额外字段(如
调试方法:
- 使用 Postman 模拟请求,确认服务器接口参数要求。
- 查看服务器日志,定位具体错误原因