下载一个非常大的文件会无声地死掉

Cov*_*Dax 5 android download android-asynctask intentservice retrofit2

所以我试图通过Retrofit2下载一个非常大的文件.文件最大可达5-10 GB.我正在从一个活动/片段启动异步结构(我已经尝试过AsyncTask和IntentService)并将文件流式传输并将字节写入内部存储器上的文件.我在每个缓冲区读取后发布filewrite的进度.

最大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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Luí*_*ues 1

这是有关下载文件的精彩教程。它可能提到您需要什么:

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);
Run Code Online (Sandbox Code Playgroud)

您的请求(本例中为 POST)应如下所示:

@Multipart
@POST("/api/v1/me/account/upload-cover") // upload avatar
Call<ResponseChangeAvatar> sendChangeAvatarRequest(@Part MultipartBody.Part file, @Header("Authorization") String token);
Run Code Online (Sandbox Code Playgroud)

改造文档(只需搜索 multipart):

http://square.github.io/retrofit/

在教程中,他创建了一个多部分主体以将文件上传到服务器:

https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server

希望这可以帮助。如果您找到解决方案,请告诉我。