gpt4 book ai didi

java - 使用 ServletOutputStream 在 Java servlet 中写入非常大的文件而不会出现内存问题

转载 作者:IT老高 更新时间:2023-10-28 20:50:06 25 4
gpt4 key购买 nike

我正在使用 IBM Websphere Application Server v6 和 Java 1.4,并尝试将大型 CSV 文件写入 ServletOutputStream 以供用户下载。目前文件大小在 50-750MB 之间。

较小的文件不会造成太大的问题,但是对于较大的文件,它似乎被写入堆中,这会导致 OutOfMemory 错误并关闭整个服务器。

这些文件只能通过 HTTPS 提供给经过身份验证的用户,这就是为什么我通过 Servlet 为它们提供服务,而不是仅仅将它们粘贴在 Apache 中。

我正在使用的代码是(在此周围删除了一些绒毛):

    resp.setHeader("Content-length", "" + fileLength);
resp.setContentType("application/vnd.ms-excel");
resp.setHeader("Content-Disposition","attachment; filename=\"export.csv\"");

FileInputStream inputStream = null;

try
{
inputStream = new FileInputStream(path);
byte[] buffer = new byte[1024];
int bytesRead = 0;

do
{
bytesRead = inputStream.read(buffer, offset, buffer.length);
resp.getOutputStream().write(buffer, 0, bytesRead);
}
while (bytesRead == buffer.length);

resp.getOutputStream().flush();
}
finally
{
if(inputStream != null)
inputStream.close();
}

FileInputStream 似乎没有引起问题,就好像我写入另一个文件或者只是完全删除写入内存使用似乎没有问题。

我在想的是 resp.getOutputStream().write 被存储在内存中,直到数据可以发送到客户端。所以整个文件可能会被读取并存储在 resp.getOutputStream() 中,导致我的内存问题和崩溃!

我尝试过缓冲这些流,也尝试过使用 java.nio 中的 Channels,但似乎对我的内存问题没有任何影响。我还刷新了 OutputStream 每次循环迭代和循环之后,这没有帮助。

最佳答案

默认情况下,一般的 servletcontainer 本身每 ~2KB 刷新一次流。当从一个和相同的来源。例如,在 Tomcat(和 Websphere!)中,这可配置为 HTTP 连接器的 bufferSize 属性。

一般的 servletcontainer 也只是将数据流式传输到 chunks如果事先不知道内容长度(根据 Servlet API specification !)并且客户端是否支持 HTTP 1.1。

问题症状至少表明 servletcontainer 在刷新之前正在缓冲内存中的整个流。这可能意味着未设置内容长度 header 和/或 servletcontainer 不支持分 block 编码和/或客户端不支持分 block 编码(即它使用的是 HTTP 1.0)。

要修复一个或另一个,只需预先设置内容长度:

response.setContentLengthLong(new File(path).length());

或者当您还没有使用 Servlet 3.1 时:

response.setHeader("Content-Length", String.valueOf(new File(path).length()));

关于java - 使用 ServletOutputStream 在 Java servlet 中写入非常大的文件而不会出现内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/685271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com