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

当我尝试从服务器下载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(); 

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

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

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

不幸的是你没有提到什么类型。 如果你有内存问题我猜它是ByteArrayOutpoutStream 。 因此,用FileOutputStream替换它,并将您正在下载的字节直接写入文件。

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

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

 FileInputStream in = new FileInputStream(file); 

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