我正在使用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();
}
Run Code Online (Sandbox Code Playgroud)
在FileInputStream
似乎没有,如果我写到另一个文件或只是删除完全写入内存使用情况似乎并不成为一个问题而导致问题.
我的想法是resp.getOutputStream().write
存储在内存中,直到数据可以发送到客户端.因此整个文件可能会被读取并存储在resp.getOutputStream()
导致我的内存问题和崩溃的位置!
我已经尝试过缓冲这些流,并尝试使用Channels java.nio
,其中任何一个似乎都没有对我的内存问题产生任何影响.我还在OutputStream
每次迭代循环和循环之后刷新了一次,这没有帮助.
我想模拟System.Diagnostics.Process.Start调用,所以我为系统程序集添加了一个Fakes Assembly.
问题是Start是System.Diagnostics.Process上的一个静态方法,所以我没有得到一个垫片,能够在Start方法的委托上进行操作.
这样做的正确方法是什么?