Java堆空间(具有大型文件的CMS)
编辑: 找到了活目录。现在还有另一个问题: 存储区中的文件以其DB id作为前缀进行存储 到他们的文件名。当然,我不想让用户看到这些 有没有办法将response.redirect和header设置结合起来 für文件名和大小 最好的 你好 新方法: 可以在tomcat中创建类似IIS的虚拟目录吗 要避免流式传输并仅使用标头重定向?我和他一起玩 但是不能让它继续下去 有什么想法吗Java堆空间(具有大型文件的CMS),java,memory,tomcat,Java,Memory,Tomcat,编辑: 找到了活目录。现在还有另一个问题: 存储区中的文件以其DB id作为前缀进行存储 到他们的文件名。当然,我不想让用户看到这些 有没有办法将response.redirect和header设置结合起来 für文件名和大小 最好的 你好 新方法: 可以在tomcat中创建类似IIS的虚拟目录吗 要避免流式传输并仅使用标头重定向?我和他一起玩 但是不能让它继续下去 有什么想法吗 thx A 嗨%, 我面临着java堆空间的一个有线问题,这个问题很接近 把我带到绳子上 简短的版本是:
thx
A
嗨%,
我面临着java堆空间的一个有线问题,这个问题很接近
把我带到绳子上
简短的版本是:
我已经编写了一个内容管理系统,需要处理
也有巨大的文件(>600mb)。Tomcat堆设置:
-Xmx700m
-Xms400m
问题是,上传巨大的文件即使是
慢点。下载文件会导致java堆空间异常
尝试下载370mb文件会使tomcat跳转到500mb堆
(应该可以)并以Java堆空间异常结束
我不明白,为什么上传有效而下载无效?
以下是我的下载代码:
byte[] byt = new byte[1024*1024*2];
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
FileInputStream fis = null;
OutputStream os = null;
fis = new FileInputStream(new File(filePath));
os = response.getOutputStream();
BufferedInputStream buffRead = new BufferedInputStream(fis);
while((read = buffRead.read(byt))>0)
{
os.write(byt,0,read);
os.flush();
}
buffRead.close();
os.close();
如果我做对了,缓冲读卡器应该处理所有的问题
内存问题,对吗
我没有主意了,任何帮助都将不胜感激
致以最良好的祝愿
W应用程序中是否有任何筛选器,或者是否使用tcnative库?你可以试着用jvisualvm来分析它 编辑:小备注:注意,如果不清理文件名,则setHeader中可能存在HTTP响应拆分攻击 如果我做对了,缓冲 读者应该注意任何记忆 问题,对吗 不,这与内存问题无关,实际上没有必要,因为您已经在使用缓冲区读取文件。你的问题在于写作,而不是阅读 我看不出你的代码有什么问题。看起来Tomcat正在缓冲整个响应,而不是流式传输。我不确定是什么原因造成的
response.getBufferSize()
返回什么?您应该尝试将response.setContentLength()
设置为文件大小;我模模糊糊地记得,在某些情况下,web容器会缓冲整个响应以确定内容长度,所以可能就是这样。无论如何,这样做是一种很好的做法,因为它使客户端能够显示下载大小并给出下载的ETA。尝试使用ServletResponse的方法和方法。您最好使用,这样您就可以部分阅读资源并释放已经流式传输的资源
否则,尽管您对JVM环境进行了设置,最终还是会出现内存问题。我的建议:
快速n简单:使用更小的数组!是的,它会循环更多,但这不会是一个问题。5千字节就可以了。您将在几分钟内知道这是否适合您
byte[] byt = new byte[1024*5];
稍微难一点:若您有权访问sendfile(比如在Tomcat中使用Http11NioProtocol
--),那个么就使用它
再难一点:将代码切换到Java NIO的FileChannel。我有非常非常相似的代码运行在同样大的文件上,有数百个并发连接和类似的内存设置,没有问题。在这些情况下,NIO比普通的旧Java流更快。它使用了DMA()的魔力,允许数据从磁盘传输到NIC,而无需经过RAM或CPU。这是我自己的代码库的一个代码片段……我已经撕下了很多来展示基本知识。FileChannel.transferTo()不能保证发送每个字节,因此它在这个循环中
WritableByteChannel destination = Channels.newChannel(response.getOutputStream());
FileChannel source = file.getFileInputStream().getChannel();
while (total < length) {
long sent = source.transferTo(start + total, length - total, destination);
total += sent;
}
WritableByteChannel destination=Channels.newChannel(response.getOutputStream());
FileChannel source=file.getFileInputStream().getChannel();
while(总长度<长度){
长发送=源.transferTo(开始+总计,长度-总计,目的地);
总数+=已发送;
}
以下代码能够将数据流传输到客户端,只分配一个小的缓冲区(缓冲区大小,这是一个软点,因为您可能需要调整它):
private static final int OUTPUT\u SIZE=1024*1024*50;//50MB
私有静态最终整数缓冲区大小=4096;
@凌驾
受保护的void doGet(HttpServletRequest请求、HttpServletResponse响应)
抛出ServletException、IOException{
字符串fileName=“42.txt”;
//生成响应头
答复:setStatus(200);
setContentLength(输出大小);
response.setContentType(“文本/普通”);
response.setHeader(“内容处置”,
“附件;文件名=\”“+文件名+\”);
response.flushBuffer();//将HTTP头写入客户端
//流结果
InputStream文件InputStream=新的InputStream(){//伪输入流
int i=0;
@凌驾
public int read()引发IOException{
if(i++<输出大小){
返回42;
}否则{
返回-1;
}
}
};
ReadableByteChannel输入=Channels.newChannel(fileInputStream);
WritableByteChannel输出=Channels.newChannel(
response.getOutputStream());
ByteBuffer缓冲区=ByteBuffer.allocate(缓冲区大小);
while(输入.读取(缓冲区)!=-1){
flip();
输出。写入(缓冲区);
buffer.clear();
}
input.close();
output.close();
}
为什么不使用tomcat自己的FileServlet
它确实可以提供比你想象的要好得多的文件。2兆字节的缓冲区太大了!几个k就足够了。对于gar来说,兆字节大小的对象是一个真正的问题
WritableByteChannel destination = Channels.newChannel(response.getOutputStream());
FileChannel source = file.getFileInputStream().getChannel();
while (total < length) {
long sent = source.transferTo(start + total, length - total, destination);
total += sent;
}
private static final int OUTPUT_SIZE = 1024 * 1024 * 50; // 50 Mb
private static final int BUFFER_SIZE = 4096;
@Override
protected void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
String fileName = "42.txt";
// build response headers
response.setStatus(200);
response.setContentLength(OUTPUT_SIZE);
response.setContentType("text/plain");
response.setHeader("Content-Disposition",
"attachment;filename=\"" + fileName + "\"");
response.flushBuffer(); // write HTTP headers to the client
// streaming result
InputStream fileInputStream = new InputStream() { // fake input stream
int i = 0;
@Override
public int read() throws IOException {
if (i++ < OUTPUT_SIZE) {
return 42;
} else {
return -1;
}
}
};
ReadableByteChannel input = Channels.newChannel(fileInputStream);
WritableByteChannel output = Channels.newChannel(
response.getOutputStream());
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
while (input.read(buffer) != -1) {
buffer.flip();
output.write(buffer);
buffer.clear();
}
input.close();
output.close();
}