本文是RxJava<第三十二篇>:RxJava+Retrofit+OkHttp+MVP的扩展,着重分析单文件上传
、单文件下载
。
本章重点想展示一下上传和下载的进度是如何实现的,后续会推出一个完整封装:RxJava+RxBinding+Retrofit+OkHttp+MVP+Dagger2
来实现get请求、post请求、单文件上传、单文件下载、多文件上传、多文件下载
(1)Retrofit+OkHttp实现文件上传
第一步
自定义带进度条文件体
/**
* 带进度条的RequestBody封装
*/
public class ProgressRequestBody extends RequestBody {
private File mFile;
private String mMediaType;//文件类型
private UploadResultListener mListener;//上传结果回调监听
private int bufferSize = 1024;//缓存大小
public ProgressRequestBody(final File file, String mediaType, final UploadResultListener listener) {
mFile = file;
mMediaType = mediaType;
mListener = listener;
}
public ProgressRequestBody(final File file, String mediaType, int eachBufferSize, final UploadResultListener listener) {
mFile = file;
mMediaType = mediaType;
bufferSize = eachBufferSize;
mListener = listener;
}
@Override
public MediaType contentType() {
return MediaType.parse(mMediaType);
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = mFile.length();
byte[] buffer = new byte[bufferSize];
FileInputStream in = new FileInputStream(mFile);
long uploaded = 0;
try {
int read;
Handler handler = new Handler(Looper.getMainLooper());
while ((read = in.read(buffer)) != -1) {
handler.post(new ProgressUpdate(uploaded, fileLength));
uploaded += read;
sink.write(buffer, 0, read);
}
} finally {
in.close();
}
}
private class ProgressUpdate implements Runnable {
private long mUploaded;
private long mTotal;
public ProgressUpdate(long uploaded, long total) {
mUploaded = uploaded;
mTotal = total;
}
@Override public void run() {
mListener.onProgressChange((int) (100 * mUploaded / mTotal));
}
}
}
第二步
上传文件结果回调监听
/**
* 上传文件监听接口
*/
public interface UploadResultListener {
void onProgressChange(int percent);//进度变化回调
void onFinish();//上传完成回调
void onInterrupted();//上传中断回调
}
第三步
retrofit接口定义
public interface FileAPIService {
//文件上传
@Multipart
@POST("FileUpload/FileUploadServlet")
Call<ResponseBody> uploadFlie(@Part MultipartBody.Part file);
}
第四步
实现
UploadResultListener uploadResultListener = new UploadResultListener() {
@Override
public void onProgressChange(int percent) {
//进度条更新
Log.d("aaa", "percent:"+percent + "%");
((TextView)findViewById(R.id.result_text1)).setText("当前上传进度:" + percent + "%");
}
@Override
public void onFinish() {
//上传完成
((TextView)findViewById(R.id.result_text1)).setText("上传完成");
}
@Override
public void onInterrupted() {
//上传中断
((TextView)findViewById(R.id.result_text1)).setText("上传失败");
}
};
findViewById(R.id.bt_1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//单文件上传
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.0.105:8080")
.build();
FileAPIService fileAPIService = retrofit.create(FileAPIService.class);
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "myapk.apk");
// 创建 RequestBody
ProgressRequestBody progressRequestBody = new ProgressRequestBody(file, "application/otcet-stream", uploadResultListener);
//新建Part
MultipartBody.Part body = MultipartBody.Part.createFormData("myapk", file.getName(), progressRequestBody);
Call<ResponseBody> call = fileAPIService.uploadFlie(body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response != null && response.isSuccessful()){
uploadResultListener.onFinish();
}else{
uploadResultListener.onInterrupted();
}
}
@Override
public void onFailure(Call call, Throwable t) {
uploadResultListener.onInterrupted();
}
});
}
});
总体四步就可以实现文件的上传,其中第一步是带进度上传文件的核心。
效果如下:
图片.png 图片.png
(2)Retrofit+OkHttp实现文件下载
第一步
下载结果回调监听
public interface DownloadResultListener {
void onProgressChange(int percent);//进度变化回调
void onFinish();//下载完成回调
void onInterrupted();//下载中断回调
}
第二步
retrofit接口定义
public interface FileAPIService {
@Streaming
@GET("/1.apk")
Call<ResponseBody> downloadFile();
}
第三步
实现
DownloadResultListener downloadResultListener = new DownloadResultListener() {
@Override
public void onProgressChange(int percent) {
//进度条更新
((TextView)findViewById(R.id.result_text2)).setText("当前下载进度:" + percent+ "%");
}
@Override
public void onFinish() {
//上传完成
((TextView)findViewById(R.id.result_text2)).setText("下载完成");
}
@Override
public void onInterrupted() {
//上传中断
((TextView)findViewById(R.id.result_text2)).setText("下载失败");
}
};
findViewById(R.id.bt_2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//文件下载
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://192.168.0.105:8080").build();
FileAPIService searchFileAPIService = retrofit.create(FileAPIService.class);
Call<ResponseBody> call = searchFileAPIService.downloadFile();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response != null && response.isSuccessful()){
new Thread(new Runnable() {
@Override
public void run() {
boolean writtenToDisk = writeResponseBodyToDisk(response.body(), downloadResultListener);
downloadResultListener.onFinish();
}
}).start();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
downloadResultListener.onInterrupted();
}
});
}
});
//写入到磁盘根目录
private boolean writeResponseBodyToDisk(ResponseBody body, DownloadResultListener downloadResultListener) {
try {
File futureStudioIconFile = new File(Environment.getExternalStorageDirectory() + File.separator + "mydownloadapk.apk");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
int fileSize = (int) body.contentLength();
int fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
final int finalFileSizeDownloaded = fileSizeDownloaded;
runOnUiThread(new Runnable() {
@Override
public void run() {
downloadResultListener.onProgressChange(100 * finalFileSizeDownloaded / fileSize);
}
});
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
效果如下:
图片.png 图片.png
网友评论