我正在使用HttpURLConnection向服务器写入文件,其中一些文件很大.
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
Run Code Online (Sandbox Code Playgroud)
前一阵子我写了1 GB或更多的对象.我通过将其设置为流更易管理的块大小来修复它.
final int bufferSize = 1024 * 1024;
[...]
conn.setChunkedStreamingMode(bufferSize);
Run Code Online (Sandbox Code Playgroud)
它在我的笔记本电脑上运行良好,但在其他机器上却崩溃了.经过调查,我发现原因是在写入输出流时发生了内存不足错误.
final OutputStream out = conn.getOutputStream();
final long bytesWritten = IOUtils.copyLarge(in, out);
Run Code Online (Sandbox Code Playgroud)
在copyLarge例程中,我发现它能够执行262145次4096字节的迭代,当它试图越过1 GB行时失败.为java应用程序分配更多内存似乎可以防止这些崩溃,但我认为这应该是不必要的.如果它正在写1 MB的块,那么它应该失败,迭代次数少得多,或者反复写1 MB而没有问题.
更新:结果显示在某些机器上实际上没有调用ChunkedStreamingMode的行设置.如果您没有设置固定/分块流模式,HttpURLConnection只会将所有内容发送到PosterOutputStream/ByteArrayOutputStream.
我已经搜索了许多处理过这个HttpRetryException问题的人的地方,但我找到的所有问题都遇到了一些名为CXF的apache服务,我没有使用它.我使用的是java.net.HttpURLConnection.我创建一个连接,使用setRequestProperty进行"授权",获取输出流,写入一堆字节,然后尝试读取回复输入流.大部分时间都有效,但有时我会得到上面提到的例外.我无法避免流式传输,因为有时我需要编写比存储在内存中更大的文件,无论如何,我发现搜索的大部分结果都表明这不是真正的问题.他们通常提供解决方案,bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");
我不使用cxf或任何其他包装器通过HttpURLConnection,并且没有服务或绑定提供程序来引用.使用setRequestProperty设置的用户名和密码在大多数情况下都可以正常进行身份验证.我希望我能说出可靠地复制错误所需的特定前提条件,但到目前为止它已被击中或未命中.