RxJava+Retrofit+OkHttp实现文件上传

背景

在实际运用中上传是一个必不可少的功能,所以我们在封装二的基础上加入上传的功能,同时需要附带上传进度!

效果

实现

1.定义service接口

注意:Multipart是指定大文件上传过程中的标示,一般上传图片的过程中我们需要附带信息,所以我们需要用到@part指定传递的数值,MultipartBody.Part是指定传递的文件;

/*上传文件*/

@Multipart

@POST("AppYuFaKu/uploadHeadImg")

Observable<BaseResultEntity<UploadResulte>> uploadImage(@Part("uid") RequestBody uid, @Part("auth_key") RequestBody auth_key,@Part MultipartBody.Part file);

2.加入进度条

retrofit是基于okhttp的处理,所以我们可以自定义RequestBody,复写writeTo(BufferedSink sink)方法,得到传递的进度数据

public class ProgressRequestBody extends RequestBody {

//实际的待包装请求体

private final RequestBody requestBody;

//进度回调接口

private final UploadProgressListener progressListener;

//包装完成的BufferedSink

private BufferedSink bufferedSink;

public ProgressRequestBody(RequestBody requestBody, UploadProgressListener progressListener) {

this.requestBody = requestBody;

this.progressListener = progressListener;

}

/**

* 重写调用实际的响应体的contentType

* @return MediaType

*/

@Override

public MediaType contentType() {

return requestBody.contentType();

}

/**

* 重写调用实际的响应体的contentLength

* @return contentLength

* @throws IOException 异常

*/

@Override

public long contentLength() throws IOException {

return requestBody.contentLength();

}

/**

* 重写进行写入

* @param sink BufferedSink

* @throws IOException 异常

*/

@Override

public void writeTo(BufferedSink sink) throws IOException {

if (null == bufferedSink) {

bufferedSink = Okio.buffer(sink(sink));

}

requestBody.writeTo(bufferedSink);

//必须调用flush,否则最后一部分数据可能不会被写入

bufferedSink.flush();

}

/**

* 写入,回调进度接口

* @param sink Sink

* @return Sink

*/

private Sink sink(Sink sink) {

return new ForwardingSink(sink) {

//当前写入字节数

long writtenBytesCount = 0L;

//总字节长度,避免多次调用contentLength()方法

long totalBytesCount = 0L;

@Override

public void write(Buffer source, long byteCount) throws IOException {

super.write(source, byteCount);

//增加当前写入的字节数

writtenBytesCount += byteCount;

//获得contentLength的值,后续不再调用

if (totalBytesCount == 0) {

totalBytesCount = contentLength();

}

Observable.just(writtenBytesCount).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Long>() {

@Override

public void call(Long aLong) {

progressListener.onProgress(writtenBytesCount, totalBytesCount);

}

});

}

};

}

}

3自定义接口,回调progress进度

public interface UploadProgressListener {

/**

* 上传进度

* @param currentBytesCount

* @param totalBytesCount

*/

void onProgress(long currentBytesCount, long totalBytesCount);

}

4创建RequestBody对象,加入进度

File file=new File("/storage/emulated/0/Download/11.jpg");

RequestBody requestBody=RequestBody.create(MediaType.parse("image/jpeg"),file);

MultipartBody.Part part= MultipartBody.Part.createFormData("file_name", file.getName(), new ProgressRequestBody(requestBody,

new UploadProgressListener() {

@Override

public void onProgress(long currentBytesCount, long totalBytesCount) {

tvMsg.setText("提示:上传中");

progressBar.setMax((int) totalBytesCount);

progressBar.setProgress((int) currentBytesCount);

}

}));

5.传递附带信息

和封装二中post请求的方式一样,我们需要继承baseentity,复写里面的方法,然后设置需要传递的参数,因为是测试接口,所以我的参数直接写死在entity里面,part文件动态指定

/**

* 上传请求api

* Created by WZG on 2016/10/20.

*/

public class UplaodApi extends BaseEntity {

/*需要上传的文件*/

private MultipartBody.Part part;

public UplaodApi(HttpOnNextListener listener, RxAppCompatActivity rxAppCompatActivity) {

super(listener, rxAppCompatActivity);

setShowProgress(true);

}

public MultipartBody.Part getPart() {

return part;

}

public void setPart(MultipartBody.Part part) {

this.part = part;

}

@Override

public Observable getObservable(HttpService methods) {

RequestBody uid= RequestBody.create(MediaType.parse("text/plain"), "4811420");

RequestBody key = RequestBody.create(MediaType.parse("text/plain"), "21f8d9bcc50c6ac1ae1020ce12f5f5a7");

return methods.uploadImage(uid,key,getPart());

}

}

6.post请求处理

请求和封装二中的请求一样,通过传递一个指定的HttpOnNextListener 对象来回调来监听结果信息,一一对应

private void uploadeDo(){

File file=new File("/storage/emulated/0/Download/11.jpg");

RequestBody requestBody=RequestBody.create(MediaType.parse("image/jpeg"),file);

MultipartBody.Part part= MultipartBody.Part.createFormData("file_name", file.getName(), new ProgressRequestBody(requestBody,

new UploadProgressListener() {

@Override

public void onProgress(long currentBytesCount, long totalBytesCount) {

tvMsg.setText("提示:上传中");

progressBar.setMax((int) totalBytesCount);

progressBar.setProgress((int) currentBytesCount);

}

}));

UplaodApi uplaodApi = new UplaodApi(httpOnNextListener,this);

uplaodApi.setPart(part);

HttpManager manager = HttpManager.getInstance();

manager.doHttpDeal(uplaodApi);

}

/**

* 上传回调

*/

HttpOnNextListener httpOnNextListener=new HttpOnNextListener<UploadResulte>() {

@Override

public void onNext(UploadResulte o) {

tvMsg.setText("成功");

Glide.with(MainActivity.this).load(o.getHeadImgUrl()).skipMemoryCache(true).into(img);

}

@Override

public void onError(Throwable e) {

super.onError(e);

tvMsg.setText("失败:"+e.toString());

}

};

以上是 RxJava+Retrofit+OkHttp实现文件上传 的全部内容, 来源链接: utcz.com/z/313589.html

回到顶部