如何使用 Volley 上传大文件? ( Android )

How is it possible to upload large files with Volley? ( Android )

我想使用 Volley 在 POST 请求中上传大文件。我尝试使用 VolleyMultiPartRequest 库,但我得到 java.lang.OutOfMemoryError:

2020-11-13 19:14:06.636 18802-18802/com.example.myproject E/MainActivity: Tried to start foreground service from background
2020-11-13 19:14:09.730 18802-19082/com.example.myproject E/AndroidRuntime: FATAL EXCEPTION: Thread-15
    Process: com.example.myproject, PID: 18802
    java.lang.OutOfMemoryError: Failed to allocate a 303955984 byte allocation with 8388608 free bytes and 108MB until OOM, max allowed footprint 162626224, growth limit 268435456
        at java.util.Arrays.copyOf(Arrays.java:3164)
        at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
        at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
        at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
        at com.example.myproject.utils.VolleyMultiPartRequest2.getBody(VolleyMultiPartRequest2.java:109)
        at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:275)
        at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:249)
        at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:94)
        at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:123)
        at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:131)
        at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:111)
        at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:90)

VolleyPlus MultiPartRequest 这样的所有库都覆盖了函数 public byte[] getBody()。这似乎是问题所在,因为如果将大文件转换为字节数组,那么它就无法装入内存。我需要分块发送请求。这怎么可能?

读这个:Volley Issue

来自 link:“它[volley] 本质上要求完整的 request/response 可存储在内存中,对于视频上传来说,通过网络从另一个来源(即磁盘),以支持部分上传的恢复等,而 Volley 的 API 本质上不支持。"

正如@CommonsWare 在问题下方的评论中提到的那样 - 你应该放弃 Volley(至少现在)。前段时间他们甚至想弃用 Volley,因为它依赖于自 API 23 以来已弃用的 Apache HttpClient,但据我所知 google 仍然支持它并有意使其更现代。

现在坚持使用 Retrofit and/or underlying OkHttp,它利用流 upload/download 而不是完全加载到内存。有了这些你就不会遇到这样的问题了。

Volley 在大文件上传方面存在一些已知问题。

对大文件使用分段文件上传,例如(改造):

public interface FileUploadService {

    @Multipart
    @POST("/upload")
    void upload(@Part("myfile") TypedFile file,
                @Part("description") String description,
                Callback<String> cb);
}

供您参考:https://futurestud.io/blog/retrofit-how-to-upload-files/