Android - 如何使用 OkHTTP 分块上传视频?

标签 android video okhttp

请查看我用于将视频上传到服务器的以下代码。但是,对于足够大的视频,我会遇到 OutOfMemory 异常。

        InputStream stream = getContentResolver().openInputStream(videoUri);
        byte[] byteArray = IOUtils.toByteArray(stream);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", "fname",
                        RequestBody.create(MediaType.parse("video/mp4"), byteArray))
                .build();
        Request request = new Request.Builder()
                .url(uploadURL)
                .post(requestBody)
                .build();

        OkHttpClient client = new OkHttpClient.Builder().build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
            }
        });

有人能为我指出正确的方向,帮助我避免 OutOfMemory 异常吗?有什么方法可以从 InputStream 转到 requestBody?

最佳答案

您可以创建一个自定义的 RequestBody 来传输数据。您必须小心:它可能会被多次重用,因为 OkHttp 可能会决定重试请求。确保每次都能从头开始重新打开 InputStream

ContentResolver contentResolver = context.getContentResolver();
final String contentType = contentResolver.getType(videoUri);
final AssetFileDescriptor fd = contentResolver.openAssetFileDescriptor(videoUri, "r");
if (fd == null) {
    throw new FileNotFoundException("could not open file descriptor");
}
RequestBody videoFile = new RequestBody() {
    @Override public long contentLength() { return fd.getDeclaredLength(); }
    @Override public MediaType contentType() { return MediaType.parse(contentType); }
    @Override public void writeTo(BufferedSink sink) throws IOException {
        try (InputStream is = fd.createInputStream()) {
            sink.writeAll(Okio.buffer(Okio.source(is)));
        }
    }
};
RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("file", "fname", videoFile)
        .build();
Request request = new Request.Builder()
        .url(uploadURL)
        .post(requestBody)
        .build();
client.newCall(request).enqueue(new Callback() {
    @Override public void onFailure(Call call, IOException e) {
        try {
            fd.close();
        } catch (IOException ex) {
            e.addSuppressed(ex);
        }
        Log.e(TAG, "failed", e);
    }
    @Override public void onResponse(Call call, Response response) throws IOException {
        fd.close();
    }
});

关于Android - 如何使用 OkHTTP 分块上传视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45123696/

相关文章:

android - 获取键盘上的 MotionEvent

java - 未指定模块?

android - 在 Okhttp 中处理身份验证

Android JSON POST 与 OKHTTP

android - 无法记录某些行

android - Python - MySQL 数据库更改后向 Android 应用程序发送通知

android - 使用 LiveCode 的自动对焦字段

iframe - 我可以将自定义视频 iframe 引入 Jekyll markdown 博客吗?

javascript - 检查 <video> 中是否存在暂停()(Windows 上的 Safari 5.1.7 - HTML5 视频)

ios - 使用 AVCam 在视频录制期间禁用自动对焦