微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 发送HTTP时的OutputStream OutOfMemoryError

我试图将一个大的视频/图像文件从本地文件系统发布到http路径,但是在一段时间后我遇到内存不足错误

这里是代码

public boolean publishFile(URI publishTo,String localPath) throws Exception {
    InputStream istream = null;
    OutputStream ostream = null;
    boolean isPublishSuccess = false;

    URL url = makeURL(publishTo.getHost(),this.port,publishTo.getPath());
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();


    if (conn != null) {

        try {

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("PUT");
            istream = new FileInputStream(localPath);
            ostream = conn.getoutputStream();

            int n;
            byte[] buf = new byte[4096];
            while ((n = istream.read(buf,buf.length)) > 0) {
                ostream.write(buf,n); //<--- ERROR happens on this line.......???
            }

            int rc = conn.getResponseCode();

            if (rc == 201) {
                isPublishSuccess = true;
            }

        } catch (Exception ex) {
            log.error(ex);
        } finally {
            if (ostream != null) {
                ostream.close();
            }

            if (istream != null) {
                istream.close();
            }
        }
    }

    return isPublishSuccess;

}

HEre是我正在收到的错误

Exception in thread "Thread-8773" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2786)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
    at sun.net.www.http.PosterOutputStream.write(PosterOutputStream.java:61)
    at com.test.HTTPClient.publishFile(HTTPClient.java:110)
    at com.test.HttpFileTransport.put(HttpFileTransport.java:97)

解决方法

HttpUrlConnection正在缓冲数据,以便它可以设置Content-Length头(每 HTTP spec).

一种替代方案,如果您的目标服务器支持它,则使用“chunked”传输.这将一次缓冲一小部分数据.然而,并不是所有的服务都支持它(例如,Amazon S3)不支持.

一个选择(而且更好的一个)是使用Jakarta HttpClient.您可以在文件的请求中设置“实体”,并且连接代码将适当地设置请求头.

编辑:nos评论说OP可以调用HttpURLConnection.setFixedLengthStreamingMode(long length).我不知道这种方法;它在1.5中被添加,从那时起我还没有使用这个类.

但是,我仍然建议使用Jakarta HttpClient,因为它减少了OP必须维护的代码量.代码是样板,但仍然有潜在的错误

> OP正确处理在输入和输出之间复制的循环.通常当我看到一个例子,海报没有正确检查返回的缓冲区大小,或者不断重新分配缓冲区.恭喜,但您现在必须确保您的继任者非常小心.
>异常处理不太好.是的,OP记得在一个最后的块中关闭连接,再次恭喜你.除了close()调用可能抛出IOException之外,保持另一个不执行.而且整个方法抛出异常,所以编译器不会帮助捕获类似的错误.
>我计算31行代码来设置和执行响应(不包括响应代码检查和URL计算,但包括try / catch / finally).使用HttpClient,这将在几十个LOC的范围内.

即使OP完美地编写了这段代码,并将其重构成类似于Jakarta Commons IO的方法,他/他不应该这样做.此代码已经被其他人编写和测试.我知道这是浪费我改写的时间,并怀疑这是浪费OP的时间.

原文地址:https://www.jb51.cc/java/125046.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐