【问题标题】:Android OutOfMemoryException while uploading file on HTTPS在 HTTPS 上上传文件时出现 Android OutOfMemoryException
【发布时间】:2011-12-21 11:36:24
【问题描述】:

我在通过 https (HttpsURLConnection) 上传文件时遇到问题。 对 HttpURLConnection 使用相同的代码就像一个魅力。

这是堆栈:

ERROR/dalvikvm-heap(29984): Out of memory on a 20932172-byte allocation.
INFO/dalvikvm(29984): "UploadingManager" prio=5 tid=9 RUNNABLE
INFO/dalvikvm(29984):   | group="main" sCount=0 dsCount=0 obj=0x2b085018 self=0x3d4de8
INFO/dalvikvm(29984):   | sysTid=30027 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=3868056
INFO/dalvikvm(29984):   at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:~91)
INFO/dalvikvm(29984):   at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:216)
INFO/dalvikvm(29984):   at org.apache.harmony.luni.internal.net.www.protocol.http.RetryableOutputStream.write(RetryableOutputStream.java:60)
INFO/dalvikvm(29984):   at java.io.DataOutputStream.write(DataOutputStream.java:99)
INFO/dalvikvm(29984):   at com.my.app.utils.UploadingManager$UploadingThread.run(UploadingManager.java:568)

这里是代码: 初始化连接:

URL url = new URL(url_to_send); 
trustAllHosts();
connection = (HttpsURLConnection) url.openConnection();
connection.setHostnameVerifier(DO_NOT_VERIFY);
connection.setChunkedStreamingMode(maxBufferSize);

我正在使用与此处所述相同的代码来建立“trustall”ssl 连接: ssl on android strange issue(我知道他们也面临类似的问题,但我想确保我在上传过程中没有犯任何错误)

这是上传的代码:

 File uploaded_file = new File(pathToOurFile);
 file_input = new FileInputStream(uploaded_file);

 output_byte = new DataOutputStream(connection.getOutputStream());

 int maxBufferSize = 20 * 1024;
 bytesAvailable = file_input.available();
 bufferSize = Math.min(bytesAvailable, maxBufferSize);
 buffer = new byte[bufferSize];

 // Read file
 bytesRead = file_input.read(buffer, 0, bufferSize);
 already_send += bytesRead;

 while (bytesRead > 0) {

     output_byte.write(buffer, 0, bufferSize); < ----Exception occurs here
     bytesAvailable = file_input.available();
     bufferSize = Math.min(bytesAvailable, maxBufferSize);
     bytesRead = file_input.read(buffer, 0, bufferSize);
     already_send += bytesRead;

 }

 output_byte.writeBytes(endBoundary);
 output_byte.flush();

你知道我为什么会得到 OutOfMemoryException 吗?

问候, 彼得

EDIT1: 我注意到如果我省略:

connection.setChunkedStreamingMode(maxBufferSize);

使用有效的 httpUrlConnection 我遇到了同样的问题。 我知道使用 ssl 发送相同的消息会产生更长的内容长度,所以我将块大小更改为 2 * maxBufferSize 甚至 20 * maxBufferSize 但这对我:/

【问题讨论】:

    标签: android ssl https out-of-memory


    【解决方案1】:

    您要上传的文件有多大?看来您正在尝试向 output_byte 缓冲区写入约 20MB 左右的数据。

    另外,您在输出中写入了错误的字节数。

    read(buffer, 0, bufferSize); 行不保证会读取bufferSize 的字节数。读取的数量是从上面的调用中返回的:

    output_byte.write(buffer, 0, bufferSize);
    

    应该改为:

    output_byte.write(buffer, 0, bytesRead);
    

    例如,如果您读取 1024 字节并尝试每次写入 20*1024 字节,那么对于 1MB 的文件,您将有 20 倍的输出字节。这可能会导致OutOfMemory 错误。

    【讨论】:

    • 感谢您的回复!无论如何,我很确定bufferSize == bytesRead,请注意我使用的是这段代码:bytesAvailable = file_input.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize);确保 bufferSize == bytesRead。文件大小约为 15-50 MB
    • 好的,这就解释了。似乎您以 20*1024 块读取文件,但以 1 块发送。你应该把它分成更小的部分。 Android 应用程序有大约 16-64 mb 的内存限制,由操作系统强制。你不能改变它。
    • 根据 Wireshark 日志判断,我想我也在发送多个块。奇怪的是,使用普通的 HttpURLConnection 我甚至可以使用相同的代码发送 100 MB 的文件。切换到 Http(S)URLConnection 会导致所有问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 2020-02-04
    • 1970-01-01
    • 2017-09-29
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多