你好,我把实现流程完整描述一下。
背景:
我们项目要实现一个 模板下载,模板里面有个sheet(不是第一个sheet)的数据是动态查询填充上去的。模板文件存储在OSS,
OSS 会返回路径,例如:http://yunexpress-fileupload.oss-cn-shenzhen.aliyuncs.com/wos/workOrder/issueFile。
这个地址可以下载附件。
问题:
附件大小在 100-200KB 左右,每下载一次,JVM 内存飙升上百MB,次数多了,造成OOM
技术: springBoot
控制层:
PostMapping(value = "/download")
public void downloadFile(HttpServletResponse response, String ossUrl) throws Exception {
fileService.downloadFile(response, param);
}
服务实现层:
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 dynamicFillAddValues(){
return initData();
}
//初始化数据
public List initData(){
String jsonStr = "[\n" +
" {\n" +
" \"addValueCode\":\"201\",\n" +
" \"addValueName\":\"换单\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"203\",\n" +
" \"addValueName\":\"更换包装\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"206\",\n" +
" \"addValueName\":\"加固\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"207\",\n" +
" \"addValueName\":\"核重\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"205\",\n" +
" \"addValueName\":\"分箱\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"204\",\n" +
" \"addValueName\":\"合箱\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"202\",\n" +
" \"addValueName\":\"清点拍照\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"208\",\n" +
" \"addValueName\":\"核重拍照\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"209\",\n" +
" \"addValueName\":\"核材积\"\n" +
" },\n" +
" {\n" +
" \"addValueCode\":\"210\",\n" +
" \"addValueName\":\"核材积拍照\"\n" +
" }\n" +
"]";
return JSONObject.parseArray(jsonStr, AddValueService.class);
}
实体:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "AddValueService")
public class AddValueService {
@ApiModelProperty(value = "编号")
private String addValueCode;
@ApiModelProperty(value = "名称")
private String addValueName;
}