Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java堆空间(具有大型文件的CMS)_Java_Memory_Tomcat - Fatal编程技术网

Java堆空间(具有大型文件的CMS)

Java堆空间(具有大型文件的CMS),java,memory,tomcat,Java,Memory,Tomcat,编辑: 找到了活目录。现在还有另一个问题: 存储区中的文件以其DB id作为前缀进行存储 到他们的文件名。当然,我不想让用户看到这些 有没有办法将response.redirect和header设置结合起来 für文件名和大小 最好的 你好 新方法: 可以在tomcat中创建类似IIS的虚拟目录吗 要避免流式传输并仅使用标头重定向?我和他一起玩 但是不能让它继续下去 有什么想法吗 thx A 嗨%, 我面临着java堆空间的一个有线问题,这个问题很接近 把我带到绳子上 简短的版本是:

编辑:

找到了活目录。现在还有另一个问题:

存储区中的文件以其DB id作为前缀进行存储 到他们的文件名。当然,我不想让用户看到这些

有没有办法将response.redirect和header设置结合起来 für文件名和大小

最好的

你好

新方法:

可以在tomcat中创建类似IIS的虚拟目录吗 要避免流式传输并仅使用标头重定向?我和他一起玩 但是不能让它继续下去

有什么想法吗

    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();
}