所以我试图通过Retrofit2下载一个非常大的文件。文件最大可达5-10 GB。我从一个活动/片段(我已尝试过AsyncTask和IntentService)启动一个异步结构,然后将文件流式传输并将字节写入内部存储器上的文件。我在每个缓冲区读取后发布文件写入的进度。
最大150 MB左右的文件工作正常,但是当我尝试5 GB文件时,流在大约1 GB后无声地消失。我没有看到日志或logcat,也没有抛出异常。
有没有人知道发生了什么,或者我写错了什么?
public interface IFileshareDownload {
@Streaming
@GET("File/Download/{guid}")
Call<ResponseBody> downloadFileByGuid(@Path("guid") String guid);
}
public class FileshareDownloadService extends IntentService {
private static final String TAG = "[FileDownloadService]";
private static final String PATH = "/ftp/";
private static final int FILE_CHUNK_SIZE = 2 * 1024 * 1024; //2MB buffer
private String mFilename;
private String mFileshareDirectory;
private String mAbsoluteFilePath;
private String mBaseUrl;
private String mGuid;
private Long mFileSize;
private Retrofit mRetrofit;
private IFileshareDownload mDownloader;
private ResultReceiver mReceiver;
public FileshareDownloadService() {
super("FileshareDownload");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
this.mBaseUrl = intent.getStringExtra("baseUrl");
this.mGuid = intent.getStringExtra("guid");
this.mFilename = intent.getStringExtra("fileName");
this.mFileSize = intent.getLongExtra("fileSize", -1);
this.mFileshareDirectory = getApplicationContext().getFilesDir().getAbsolutePath() + PATH;
this.mAbsoluteFilePath = mFileshareDirectory + mFilename;
this.mRetrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl)
.callbackExecutor(Executors.newSingleThreadExecutor())
.build();
this.mDownloader = mRetrofit.create(IFileshareDownload.class);
this.mReceiver = intent.getParcelableExtra("listener");
downloadFile();
}
public void downloadFile() {
Call<ResponseBody> call = mDownloader.downloadFileByGuid(mGuid);
try {
Response<ResponseBody> response = call.execute();
if(response.isSuccessful()) {
File file = new File(mAbsoluteFilePath);
file.createNewFile();
try(FileOutputStream fos = new FileOutputStream(file)) {
InputStream is = response.body().byteStream();
setUpdateProgress(SHOW_PROGRESS);
int count = 0;
long bytesRead = 0;
byte[] buffer = new byte[FILE_CHUNK_SIZE];
try {
while ((count = is.read(buffer)) != -1) {
fos.write(buffer, 0, count);
fos.flush();
bytesRead += count;
int progress = getPercent(bytesRead, mFileSize);
Log.d(TAG, String.format("Read %d out of %d bytes.", bytesRead, mFileSize));
setUpdateProgress(UPDATE_PROGRESS, progress);
}
} catch (Throwable t)
{
Log.e(TAG, "What happened?", t);
}
}
setUpdateProgress(HIDE_PROGRESS);
} else {
setUpdateProgress(HIDE_PROGRESS);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
这是一个关于下载文件的精彩教程。它可能会提到你需要的东西:
https://futurestud.io/tutorials/retrofit-2-how-to-download-files-from-server
如果没有,请查看@Multipart注释以及@Part。我不确定你是否可以在GET中使用它,但由于你还没有答案,我会在这里发布,这样你就可以随意拍摄。
这是我的项目中的一个示例,我们在其中创建了一个多部分主体来上传图像。我知道你想要一个GET,但这个例子仍然是相关的:
// Setting up the multipart file
File newAvatar = new File(getRealPathFromURI(avatarUri)); // the new avatar
RequestBody filePart = RequestBody.create(MediaType.parse(getActivity().getContentResolver().getType(avatarUri)), newAvatar);
您的请求(本例中的POST)应该是这样的:
@Multipart
@POST("/api/v1/me/account/upload-cover") // upload avatar
Call<ResponseChangeAvatar> sendChangeAvatarRequest(@Part MultipartBody.Part file, @Header("Authorization") String token);
改装文档(只搜索multipart):
http://square.github.io/retrofit/
一个教程,他在其中创建了一个多部分正文以将文件上传到服务器:
https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server
希望这会有所帮助。如果您找到了解决方案,请告诉我。