我正在使用rxjava改造将一个大文件上传到android上的服务器。
我有一个大文件,我会将文件读取到一小块字节数组,然后将它放到服务器上。成功后,我会更新进度条。
但问题是,在我的情况下,我将读取50个块,每个块大小为6MB。对于前18个块,它工作正常,堆内存分配6MB,进度条平滑更新。但是从第19个块开始,进度将被冻结,并且每次创建Observable后堆大小分配越来越多。
无论如何,我仍然成功地将文件上传到服务器。
这是我的代码:
private static void processUpload(File file, final ProgressUpdater updater) throws IOException, FileNotFoundException{
final FileInputStream inputStream = new FileInputStream(file);
sCountSuccess = 0;
Observable<ResponseBody> responseBodyObservable = Observable.from(sUpload.getUploadChunk())
.flatMap(new Func1<UploadChunk, Observable<ResponseBody>>() {
@Override
public Observable<ResponseBody> call(UploadChunk uploadChunk) {
int bytesRead = -1;
try {
byte[] temp = new byte[chunkSize];
bytesRead = inputStream.read(temp);
if (bytesRead != -1) {
byte[] finalBuffer;
if (temp.length > bytesRead)
{
finalBuffer = Arrays.copyOf(temp, bytesRead);
}
else
{
finalBuffer = temp;
}
RequestBody requestBody = RequestBody.create(MediaType.parse(""), finalBuffer);
Log.d("UPLOAD_ID", uploadChunk.getUrl());
Observable<ResponseBody> responseBodyObservable = sNetworkResources.putVideo(uploadChunk.getUrl(), requestBody);
return responseBodyObservable;
}
} catch (Exception e) {
Log.e("UPLOAD_ERROR", e.getMessage());
} finally {
if(inputStream != null && bytesRead == -1) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
responseBodyObservable.subscribe(new Subscriber<ResponseBody>() {
@Override
public void onCompleted() {
updater.onProgressFinish();
commitUpload();
// }
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ResponseBody data) {
// update
sCountSuccess++;
updater.onProgressUpdate(sCountSuccess);
}
});
}
答案 0 :(得分:0)
This帖子说如果你在界面上使用@Multipart注释,你不需要自己对流进行分块:
Retrofit会将Multipart部分主体直接传输到网络,因此您发送大型主体不会导致OOM,除非您以某种方式缓冲它。
您的界面可能如下所示:
@Multipart
@PUT(VIDEO_URL)
Observable<ResponseBody> putVideo(@Url String videoUrl, @Part("file") RequestBody requestBody);