springboot从服务器下载文件,远程服务器报错文件地址找不到,本地不报错解决
1.问题发现:上篇文章写到从服务器获取PDF模板写入表单,再导出。放在本地跑正常,远程服务器会报错找不到文件。
2.分析:之前获取文件地址采用resourceLoader,将文件放在resources下面
Resource resource = resourceLoader.getResource(EntityConstant.ACTIVITY_CHECK_TEMPLATE_PATH);
String filePath;
try {
filePath = URLDecoder.decode(resource.getURL().getPath(), "utf-8");
} catch (IOException e) {
e.printStackTrace();
log.info("文件地址URL解析失败!");
return "下载失败!";
}
EntityConstant.ACTIVITY_CHECK_TEMPLATE_PATH 是我定义的常量classpath:/public/xxx.xls,拿到地址后调用静态方法 PDFUtil.writePDFAndDownload(request, response, filePath, fontPath, fileName, values); 即可(方法体是什么可以去看上一篇文章)。这样写放在本地运行可以,放到远程服务器会报错。主要是使用resourceLoader获取的地址在打包后用不了了(具体原因不知道,我也是个新手,知道的可以告诉我,哈哈)。
3.解决问题:使用ClassPathResource,将地址改为"/public/xxx.xls"
ClassPathResource classPathResource = new ClassPathResource(EntityConstant.ACTIVITY_CHECK_TEMPLATE_PATH);
InputStream is = null;
try {
is = classPathResource.getInputStream();
} catch (IOException e) {
e.printStackTrace();
log.info("文件地址URL解析失败!");
return "下载失败!";
}
使用classPathResource获取classPath下面的文件,并用classPathResource下的InputStream下的filePath和fileName代替之前的resourceLoader下的file里的filePath和fileName,关键是用InputStream代替File
String fileName = activity.getTerActivityName()
+ classPathResource.getFilename().substring(classPathResource.getFilename().lastIndexOf("."));
// 获取服务器写入PDF字体文件
classPathResource = new ClassPathResource(EntityConstant.PDF_FONT_PATH);
String fontPath = "";
fontPath = classPathResource.getPath() + ",1";
把获得的InputStream替代之前从resourceLoader获取的filePath传入PDFUtil.writePDFAndDownload(request, response, is, fontPath, fileName, values);
具体填写PDF并导出代码如下:
public String getCheckReport(String terActivityCode, HttpServletRequest request, HttpServletResponse response) {
if(terActivityCode == null) {
return "参数为空,请求失败!";
}
TerminalActivity activity = terminalActivityMapper.selectByActivityCode(terActivityCode);
if(activity == null) {
return "不存在的方案编号!";
}
// 获取服务器PDF模板文件
ClassPathResource classPathResource = new ClassPathResource(EntityConstant.ACTIVITY_CHECK_TEMPLATE_PATH);
InputStream is = null;
try {
is = classPathResource.getInputStream();
} catch (IOException e) {
e.printStackTrace();
log.info("文件地址URL解析失败!");
return "下载失败!";
}
String fileName = activity.getTerActivityName()
+ classPathResource.getFilename().substring(classPathResource.getFilename().lastIndexOf("."));
// 获取服务器写入PDF字体文件
classPathResource = new ClassPathResource(EntityConstant.PDF_FONT_PATH);
String fontPath = "";
fontPath = classPathResource.getPath() + ",1";
// 获取需要写入模板的属性值
List<TerminalExeInfoMaterial> materialList = materialMapper.selectByActivityCode(terActivityCode);
Map<String, Object> values = new HashMap<>();
// 写入方案信息
values.put("terActivityName", activity.getTerActivityName());
values.put("terActivityCustAmount", activity.getTerActivityCustAmount());
values.put("city_name", activity.getCityName());
// 写入验收信息
for(int i = 1; i <= 8; i ++) {
values.put("check" + i + "_pass", EntityConstant.CHECK_PASS_SYMBOL);
}
if(TerminalActivityStateEnum.CHECK_PASS.getValue() == activity.getState()) {
values.put("check_pass", EntityConstant.CHECK_PASS_SYMBOL);
}
// 写入材料信息
int index = 1;
for(TerminalExeInfoMaterial material : materialList) {
values.put("material_name" + index, material.getMaterialName());
values.put("material_area" + index, material.getMaterialArea());
index ++;
}
if(activity.getApplyUserId() != null) {
String checkPerson = userMapper.getUserName(activity.getApplyUserId());
if(checkPerson != null) {
values.put("check_person", checkPerson);
} else {
return "验收人查询失败!";
}
}
// values.put("check_person", userMapper.getUserName(activity.getApplyUserId()));
values.put("check_time", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
return PDFUtil.writePDFAndDownload(request, response, is, fontPath, fileName, values);
}
public static String writePDFAndDownload(HttpServletRequest request, HttpServletResponse response,
InputStream is, String fontPath, String fileName, Map<String, Object> values) {
// 处理文件名转码
String header = request.getHeader("User-Agent").toUpperCase();
try {
if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
// IE下载文件名空格变+号问题
fileName = URLEncoder.encode(fileName, "utf-8");
fileName = fileName.replace("+", "%20");
} else {
fileName = new String(fileName.getBytes(), "ISO8859-1");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "文件名编码错误!";
}
// 处理响应为下载附件形式
response.reset();
response.setContentType("multipart/form-data");
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Location", fileName);
response.setHeader("Content-Disposition", "attachment; fileName=" + fileName);
response.setHeader("Cache-Control", "max-age=0");
// 设置写入PDF的字体
try {
bf = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
return "文档字体非法";
} catch (IOException e) {
e.printStackTrace();
return "文档字体无法识别";
}
PdfReader pdfReader;
ByteArrayOutputStream baos;
PdfStamper pdfStamper;
try {
OutputStream os = response.getOutputStream();
// pdfReader = new PdfReader(filePath);
pdfReader = new PdfReader(is);
baos = new ByteArrayOutputStream();
pdfStamper = new PdfStamper(pdfReader, baos);
// 为PDF模板表单字段写入对应的值
AcroFields fields = pdfStamper.getAcroFields();
fields.addSubstitutionFont(bf);
for(Entry<String, Object> entry : values.entrySet()) {
Paragraph paragraph = new Paragraph(String.valueOf(entry.getValue()));
paragraph.setAlignment(TextAlignment.CENTER.getValue());
fields.setField(entry.getKey(), paragraph.getContent());
}
// 设置PDF为不可编辑状态true
pdfStamper.setFormFlattening(true);
pdfStamper.close();
// 将文件下载
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, os);
doc.open();
PdfImportedPage page = copy.getImportedPage(new PdfReader(baos.toByteArray()), 1);
copy.addPage(page);
// 关闭流
doc.close();
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
return "传输失败!";
} catch (DocumentException e) {
e.printStackTrace();
return "获取文档失败";
}
return null;
}