安卓传文件给服务器
- 行业动态
- 2025-04-24
- 2
通过OkHttp或Retrofit库构建Multipart请求,添加文件至RequestBody并设置Content-Type,异步执行POST上传,需动态申请存储权限,捕获IO异常并处理服务器响应状态码
安卓文件上传至服务器实现方案
权限配置
在AndroidManifest.xml中声明必要权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
注:Android 10+需动态申请存储权限,建议使用Scoped Storage
模式
文件传输方式选择
传输方式 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
HTTP POST/PUT | 常规文件上传 | 简单易用,广泛支持 | 大文件传输效率低 |
FTP协议 | 局域网传输 | 支持断点续传 | 需要服务器配置FTP服务 |
WebSocket | 实时传输 | 双向通信 | 实现复杂度高 |
HTTP文件上传实现(以Retrofit为例)
依赖配置:
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0'
创建Retrofit实例:
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(“https://yourserver.com/api/”)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
3. 定义API接口:
```java
public interface FileUploadService {
@Multipart
@POST("upload")
Call<UploadResponse> uploadFile(@Part MultipartBody.Part filePart);
}
- 构建请求体:
// 获取文件路径 File file = new File(Environment.getExternalStorageDirectory(), "test.txt");
// 创建请求体
RequestBody requestBody = RequestBody.create(MediaType.parse(“multipart/form-data”), file);
MultipartBody.Part filePart = MultipartBody.Part.createFormData(“file”, file.getName(), requestBody);
5. 执行上传:
```java
FileUploadService service = retrofit.create(FileUploadService.class);
Call<UploadResponse> call = service.uploadFile(filePart);
// 异步请求
call.enqueue(new Callback<UploadResponse>() {
@Override
public void onResponse(Call<UploadResponse> call, Response<UploadResponse> response) {
if(response.isSuccessful()){
// 处理成功逻辑
} else {
// 处理错误响应
}
}
@Override
public void onFailure(Call<UploadResponse> call, Throwable t) {
// 网络错误处理
}
});
进度监听实现
// 创建带进度的RequestBody ProgressRequestBody body = new ProgressRequestBody(requestBody, new ProgressListener() { @Override public void onProgress(long currentBytes, long totalBytes) { double progress = (double)currentBytes/totalBytes100; // 更新UI进度条 } }); // 替换原始请求体 MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), body);
常见问题解决方案
问题现象 | 解决方案 |
---|---|
文件过大导致OOM | 使用RequestBody 流式传输,避免一次性加载 |
权限被拒绝 | Android 6.0+动态申请运行时权限 |
跨域问题 | 服务器端配置CORS头 |
SSL证书验证失败 | 配置证书信任管理器或禁用验证(测试环境) |
服务器端接收示例(Node.js)
const express = require('express'); const multer = require('multer'); const app = express(); const upload = multer({ dest: 'uploads/' }); app.post('/upload', upload.single('file'), (req, res) => { // 文件已保存到uploads目录 res.json({ success: true, filename: req.file.filename }); });
相关问题与解答
Q1:如何实现文件分片上传?
A1:将文件分割为多个小块(如每块1MB),按顺序上传并记录已上传块数,服务器端需提供校验接口,全部上传完成后进行文件合并,可使用RandomAccessFile
进行文件分块读取。
Q2:如何支持多文件同时上传?
A2:使用MultipartBody.Part
数组构建请求:
MultipartBody.Part[] parts = {filePart1, filePart2, filePart3}; Call<UploadResponse> call = service.uploadMultipleFiles(parts); // 需在接口定义@PartMap或@Part注解数组
服务器端需处理数组类型的文件参数,如使用multer
的array()
方法