java下载大文件的时候报Java heap space的话其实就是jvm内存不够,大概率是把整个文件都下到内存中去了,所以这时候有两种解决方案。
第一种解决方案,增加tomcat的jvm内存,直接在tomcat的bin目录下创建一个setenv.sh的文件,内容就是 export CATALINA_OPTS="-Xms4096m -Xmx4096m" ,tomcat会优先读取设置在这里的配置,如果觉得麻烦也可以直接在catalina.sh里面加,网上有很多怎么加的,这里就不多赘述了。
第二种解决jvm内存不够的方法就是在写入文件的时候,不要直接把文件全写到流里,而是创建一个临时文件去保存。用完之后再把该临时文件给去掉,所以可以封装一个自定义流,继承文件流,实现在流关闭的时候,自动删掉临时文件。以下是代码
import cn.hutool.core.io.FileUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DownFileInputStream extends FileInputStream {
private final File file;
public DownFileInputStream(File file) throws FileNotFoundException {
super(file);
this.file = file;
}
public long getSize() {
return file.length();
}
@Override
public void close() throws IOException {
super.close();
FileUtil.del(file);
}
}
DownFileInputStream fileInputStream = null;
try {
// 创建临时文件
tempFile = File.createTempFile("temp", ".tmp");
// 获取临时文件输出流
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
// 把需要下载的文件写入fileOutputStream
省略。。。。
// 获取临时文件的输入流
fileInputStream = new DownFileInputStream(tempFile);
}catch(Exception e){
log.error(e.getMessage(), e);
}
finally{
// 关闭输出流
fileOutputStream.close();
}
除了jvm内存之外,如果用post请求下载大文件,只下载到了2G大小,其余部分被截断了的话,那么大概率是因为设置了响应头response.setContentLeng()的原因,因为这个长度默认是int类型的,浏览器根据该属性显示进度,int类型长度不够导致只下载到了2G。所以在这种情况下,可以使用response.setContentLengthLong(fileLength);用这个long的类型来设置长度。值得一提的是,如果想直接通过流来获取文件长度的话,可以使用上面封装的自定义流DownFileInputStream里的getSize方法。或者有文件的话直接file.length也可以。
当然,如果嫌麻烦的话,不用post请求,直接用get请求省事也是可以的。
希望能帮助到你,相信自己,you good good !