如何在java中下载没有内存问题的大文件

时间:2011-08-18 11:36:49

标签: java out-of-memory

当我尝试从服务器下载260MB的大文件时,我收到此错误:java.lang.OutOfMemoryError: Java heap space.我确定我的堆大小小于252MB。有没有办法在不增加堆大小的情况下下载大文件?

如何在不遇到此问题的情况下下载大文件?我的代码如下:

String path= "C:/temp.zip";   
response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\""); 
byte[] buf = new byte[1024];   
try {   

             File file = new File(path);   
             long length = file.length();   
             BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   
             ServletOutputStream out = response.getOutputStream();   

             while ((in != null) && ((length = in.read(buf)) != -1)) {   
             out.write(buf, 0, (int) length);   
             }   
             in.close();   
             out.close();

4 个答案:

答案 0 :(得分:18)

我可以看到有两个地方可能会增加内存使用量:

  1. 在缓冲区中读取输入文件。
  2. 在缓冲区写入输出流(HTTPOutputStream?)
  3. 对于#1,我建议您通过FileInputStream直接从文件中阅读而不使用BufferedInputStream。首先尝试这一点,看看它是否能解决您的问题。即:

    FileInputStream in = new FileInputStream(file);   
    

    而不是:

    BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   
    

    如果#1无法解决问题,您可以尝试在写入如此多的数据后定期刷新输出流(如果需要,减少块大小):

    即:

    try
    {
        FileInputStream fileInputStream  = new FileInputStream(file);
        byte[] buf=new byte[8192];
        int bytesread = 0, bytesBuffered = 0;
        while( (bytesread = fileInputStream.read( buf )) > -1 ) {
            out.write( buf, 0, bytesread );
            bytesBuffered += bytesread;
            if (bytesBuffered > 1024 * 1024) { //flush after 1MB
                bytesBuffered = 0;
                out.flush();
            }
        }
    }
    finally {
        if (out != null) {
            out.flush();
        }
    }
    

答案 1 :(得分:4)

很遗憾,您还没有提到out的类型。如果您有内存问题,我猜它是ByteArrayOutpoutStream。因此,将其替换为FileOutputStream并将您正在下载的字节直接写入文件。

顺便说一句,不要使用逐字节读取的read()方法。请改用read(byte[] arr)。这要快得多。

答案 2 :(得分:0)

首先,您可以从while语句中删除(in!= null),这是不必要的。其次,尝试删除BufferedInputStream,然后执行:

FileInputStream in = new FileInputStream(file);

答案 3 :(得分:0)

使用您显示的代码没有任何错误(关于内存使用情况)。 servlet容器配置为缓冲整个响应(查看web.xml配置),或者内存泄漏到其他地方。