Retrofit2 & RxJava2实现单文件和多文件上传,跨平台移动开发答案
public class RetrofitClient {private static RetrofitClient mInstance;private static Retrofit retrofit;private RetrofitClient() {retrofit = RetrofitBuilder.buildRetrofit();}/**获取RetrofitClient实例.@retur
public class RetrofitClient {
private static RetrofitClient mInstance;
private static Retrofit retrofit;
private RetrofitClient() {
retrofit = RetrofitBuilder.buildRetrofit();
}
/**
-
获取RetrofitClient实例.
-
@return 返回RetrofitClient单例
*/
public static synchronized RetrofitClient getInstance() {
if (mInstance == null) {
mInstance = new RetrofitClient();
}
return mInstance;
}
private T create(Class clz) {
return retrofit.create(clz);
}
/**
-
单上传文件的封装.
-
@param url 完整的接口地址
-
@param file 需要上传的文件
-
@param fileUploadObserver 上传回调
*/
public void upLoadFile(String url, File file,
FileUploadObserver fileUploadObserver) {
UploadFileRequestBody uploadFileRequestBody =
new UploadFileRequestBody(file, fileUploadObserver);
create(UploadFileApi.class)
.uploadFile(url, MultipartBuilder.fileToMultipartBody(file,
uploadFileRequestBody))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(fileUploadObserver);
}
/**
-
多文件上传.
-
@param url 上传接口地址
-
@param files 文件列表
-
@param fileUploadObserver 文件上传回调
*/
public void upLoadFiles(String url, List files,
FileUploadObserver fileUploadObserver) {
create(UploadFileApi.class)
.uploadFile(url, MultipartBuilder.filesToMultipartBody(files,
fileUploadObserver))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(fileUploadObserver);
}
}
这个是Retrofit客户端类,获取它的单例然后去调用它的上传文件的方法,可以看到我这里封装了两个方法,uploadFile是上传单个文件,uploadFiles方法上传多个文件.
因为我们需要构造一个Retrofit对象,所以这里有一个RetrofitBuilder类:
/**
-
Retrofit构造器.
-
@author devilwwj
-
@since 2017/7/13
*/
public class RetrofitBuilder {
private static Retrofit retrofit;
public static synchronized Retrofit buildRetrofit() {
if (retrofit == null) {
Gson gson = new GsonBuilder().setDateFormat(“yyyy-MM-dd HH:mm:ss”).create();
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);
retrofit = new Retrofit.Builder().client(OkHttpManager.getInstance())
.baseUrl(AppConfig.HTTP_SERVER)
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
}
可以看到,想构造Retrofit对象是需要获取OkhttpClient实例的。
定义上传文件接口
/**
-
上传API.
-
@author devilwwj
-
@since 2017/7/12
*/
public interface UploadFileApi {
String UPLOAD_FILE_URL = AppConfig.HTTP_SERVER + “file/upload”;
@POST
Observable uploadFile(@Url String url, @Body MultipartBody body);
}
这里就是Retrofit定义接口的形式,通过注解来表示各个参数,@POST表示发起post请求,@Url表示这是个请求地址,@Body表示这是请求体,关于Retrofit的各种注解的使用这里不多说,大家可以自行了解。
构造MultipartBody
上一步定义好了上传的接口,我们最终是要去构造MultipartBody,这一块就需要跟后台同学进行沟通了,根据接口定义来实现,这里是我们的实现:
/**
-
MultipartBuilder.
-
@author devilwwj
-
@since 2017/7/13
*/
public class MultipartBuilder {
/**
-
单文件上传构造.
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
@param file 文件
-
@param requestBody 请求体
-
@return MultipartBody
*/
public static MultipartBody fileToMultipartBody(File file, RequestBody requestBody) {
MultipartBody.Builder builder = new MultipartBody.Builder();
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(“fileName”, file.getName());
jsonObject.addProperty(“fileSha”, Utils.getFileSha1(file));
jsonObject.addProperty(“appId”, “test0002”);
builder.addFormDataPart(“file”, file.getName(), requestBody);
builder.addFormDataPart(“params”, jsonObject.toString());
builder.setType(MultipartBody.FORM);
return builder.build();
}
/**
-
多文件上传构造.
-
@param files 文件列表
-
@param fileUploadObserver 文件上传回调
-
@return MultipartBody
*/
public static MultipartBody filesToMultipartBody(List files,
FileUploadObserver fileUploadObserver) {
MultipartBody.Builder builder = new MultipartBody.Builder();
JsonArray jsonArray = new JsonArray();
Gson gson = new Gson();
for (File file : files) {
UploadFileRequestBody uploadFileRequestBody =
new UploadFileRequestBody(file, fileUploadObserver);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(“fileName”, file.getName());
jsonObject.addProperty(“fileSha”, Utils.getFileSha1(file));
jsonObject.addProperty(“appId”, “test0002”);
jsonArray.add(jsonObject);
LogUtil.d(jsonObject.toString());
builder.addFormDataPart(“file”, file.getName(), uploadFileRequestBody);
}
builder.addFormDataPart(“params”, gson.toJson(jsonArray));
LogUtil.d(gson.toJson(jsonArray));
builder.setType(MultipartBody.FORM);
return builder.build();
}
}
自定义RequestBody
构造MultipartBody是需要去创建每个文件对应的ReqeustBody,但我们这边需要监听到文件上传成功、失败和进度的状态,所以需要去自定义:
/**
-
上传文件请求body.
-
@author devilwwj
-
@since 2017/7/12
*/
public class UploadFileRequestBody extends RequestBody {
private RequestBody mRequestBody;
private FileUploadObserver fileUploadObserver;
public UploadFileRequestBody(File file, FileUploadObserver fileUploadObserver) {
this.mRequestBody = RequestBody.create(MediaType.parse(“application/octet-stream”), file);
this.fileUploadObserver = fileUploadObserver;
}
@Override
public MediaType contentType() {
return mRequestBody.contentType();
}
@Override
public long contentLength() throws IOException {
return mRequestBody.contentLength();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
CountingSink countingSink = new CountingSink(sink);
BufferedSink bufferedSink = Okio.buffer(countingSink);
// 写入
mRequestBody.writeTo(bufferedSink);
// 刷新
// 必须调用flush,否则最后一部分数据可能不会被写入
bufferedSink.flush();
}
/**
- CountingSink.
*/
protected final class CountingSink extends ForwardingSink {
private long bytesWritten = 0;
public CountingSink(Sink delegate) {
super(delegate);
}
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
bytesWritten += byteCount;
if (fileUploadObserver != null) {
fileUploadObserver.onProgressChange(bytesWritten, contentLength());
}
}
}
}
这里有个RxJava2的Observer的抽象类,主要是用来收到Rxjava2的事件:
/**
-
上传文件的RxJava2回调.
-
@author devilwwj
-
@since 2017/7/12
-
@param 模板类
*/
public abstract class FileUploadObserver extends DefaultObserver {
@Override
public void onNext(T t) {
onUploadSuccess(t);
}
@Override
public void onError(Throwable e) {
onUploadFail(e);
}
@Override
public void onComplete() {
}
// 上传成功的回调
public abstract void onUploadSuccess(T t);
// 上传失败回调
public abstract void onUploadFail(Throwable e);
// 上传进度回调
public abstract void onProgress(int progress);
// 监听进度的改变
public void onProgressChange(long bytesWritten, long contentLength) {
onProgress((int) (bytesWritten * 100 / contentLength));
}
}
ok,到现在完整的代码实现已经说完。
具体使用方法
RetrofitClient.getInstance().upLoadFiles(UploadFileApi.UPLOAD_FILE_URL, files,
new FileUploadObserver() {
@Override
public void onUploadSuccess(ResponseBody responseBody) {
if (responseBody == null) {
LogUtil.e(“responseBody null”);
return;
}
try {
JSONObject jsonObject = new JSONObject(responseBody.string());
ArrayList fileIds = new ArrayList();
fileIds.add(jsonObject.getString(“fileId”));
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
更多推荐
所有评论(0)