我正在尝试将大型视频/图像文件从本地文件系统发布到 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, 0, buf.length)) > 0) {
ostream.write(buf, 0, 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;
}
这是我遇到的错误...
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)
The HttpUrlConnection
正在缓冲数据,以便它可以设置Content-Length
标头(每HTTP规范 http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3).
如果您的目标服务器支持,另一种选择是使用“chunked http://java.sun.com/javase/6/docs/api/java/net/HttpURLConnection.html#setChunkedStreamingMode(int)“传输。这一次只会缓冲一小部分数据。但是,并非所有服务都支持它(例如,Amazon S3 就不支持)。
另一种选择(在我看来是更好的选择)是使用雅加达 HttpClient http://hc.apache.org/httpclient-3.x/apidocs/index.html。您可以在文件的请求中设置“实体”,连接代码将相应地设置请求标头。
Edit: nos评论说OP可以打电话HttpURLConnection.setFixedLengthStreamingMode(long length)
。我不知道这种方法;它是在1.5中添加的,从那以后我就没有使用过这个类。
但是,我still建议使用 Jakarta HttpClient,原因很简单,它减少了 OP 必须维护的代码量。代码是样板代码,但仍然有可能出现错误:
- OP 正确处理循环以在输入和输出之间进行复制。通常,当我看到这样的示例时,发布者要么没有正确检查返回的缓冲区大小,要么不断重新分配缓冲区。恭喜你,但你现在必须确保你的继任者同样重视。
- 异常处理不太好。是的,OP记得关闭连接
finally
块,再次祝贺你。除非其中任何一个close()
调用可能会抛出IOException
,阻止对方执行。该方法作为一个整体抛出Exception
,这样编译器就不会帮助捕获类似的错误。
- 我计算了 31 行代码来设置和执行响应(不包括响应代码检查和 URL 计算,但包括 try/catch/finally)。对于 HttpClient,这将在六个 LOC 的范围内。
即使OP完美地编写了这段代码,并将其重构为类似于Jakarta Commons IO中的方法,他/她不应该那样做。此代码已由其他人编写和测试。我知道这是浪费my是时候重写它了,并且怀疑这也是浪费OP的时间。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)