你好,我把实现流程完整描述一下。
背景: 我们项目要实现一个 模板下载,模板里面有个sheet(不是第一个sheet)的数据是动态查询填充上去的。模板文件存储在OSS, OSS 会返回路径,例如:http://yunexpress-fileupload.oss-cn-shenzhen.aliyuncs.com/wos/workOrder/issueFile1。 该 OSS 路径可以下载附件。
问题: 附件大小在 100-200KB 左右,每下载一次,JVM 内存飙升上百MB,次数多了,造成OOM
技术: springBoot
控制层:FileController
PostMapping(value = "/download") public void downloadFile(HttpServletResponse response, String ossUrl) throws Exception { fileService.downloadFile(response, param); }
服务实现层:FileServiceImpl
public void downloadFile(HttpServletResponse response, String ossUrl) throws IOException { URL url = new URL(ossUrl); URLConnection conn = url.openConnection(); conn.setConnectTimeout(3 * 1000); // 设置超时间为3秒 conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36"); InputStream inputStream = conn.getInputStream();
String fileName = "数据填充模板.xlsx";
//数据填充
issueDynamicFill(response, fileName, inputStream);
}
public void issueDynamicFill(HttpServletResponse response,
InputStream inputStream) throws IOException {
ServletOutputStream outputStream = exportHeader(response, fileName);
ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();
WriteSheet writeSheet = EasyExcel.writerSheet().sheetNo(2).build();
//dynamicFillAddValues 原本是查库的,为省略时间,数据写死
excelWriter.fill(dynamicFillAddValues(), writeSheet);
excelWriter.finish();
inputStream.close();
outputStream.flush();
}
public ServletOutputStream exportHeader(HttpServletResponse response, String fileName) throws IOException { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, CHARACTER)); return response.getOutputStream(); }
public List
//初始化数据
public List
}
实体:
@Data @Builder @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "AddValueService") public class AddValueService {
@ApiModelProperty(value = "编号")
private String addValueCode;
@ApiModelProperty(value = "名称")
private String addValueName;
}