如何在java中下载大文件而不会出现内存问题

2022-09-02 12:34:02

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

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

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

答案 1

有2个地方,我可以看到你可能会建立内存使用量:

  1. 在缓冲区中读取输入文件。
  2. 在缓冲区写入输出流(HTTPOutputStream?

对于#1,我建议通过不带.请先尝试此操作,看看它是否能解决您的问题。即:FileInputStreamBufferedInputStream

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

答案 2

不幸的是,您没有提到是什么类型。如果你有内存问题,我想它是.因此,将其替换为并将要下载的字节直接写入文件。outByteArrayOutpoutStreamFileOutputStream

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


推荐