文章目录
- 1.报错如图
- 2.项目背景
- 3.网上的解决方案
- 4.我的最终解决方案
1.报错如图
2.项目背景
我们的项目采用的全是https请求,而使用第三方文件管理器go-fastdfs,该文件管理器返回的所有下载文件的请求全是http开头的,比如http://10.110.38.253:11014/group1/batchImportData/组 (26).xlsx,然而在https请求下使用http的请求就会报如上图的错误,且不能把文件下载请求http改为https,因为修改后会查询不到文件。所以必须只能采用http的请求且想让功能实现。
注意点1:我们公司项目请求协议前缀必须是https的,执行http的无效
注意点2:这种第三方返回的文件下载路径http://10.110.38.253:11014/group1/batchImportData/组 (26).xlsx,是可以直接放在浏览器上直接下载的,具体请看如图
3.网上的解决方案
可以先看下其他人的博客,但是方案对我目前公司项目无效
1.https页面加载http资源的解决方法
2.分享 4个解决 https页面加载http资源报错的方法
问题:里面的方案为啥对我公司的项目无效?
答案:
- 针对修改协议前缀的方案,我们的必须得是https的才行,其他无效。
- 针对使用 iframe 的方案,因为没用过,且感觉项目引入会很费事且庞杂,所以当时没考虑该方案。
- 针对自动升级方案(也就是说把第三方文件管理器go-fastdfs配置文件改了,由http协议改为https协议),该方案真对我的项目不行,因为我的公司有很多老项目都是用这个文件管理器go-fastdfs,如果把协议改了,不清楚对其他服务会不会有影响,所以轻易不能动。
综上所述:上面的方案我一个都不能用,所以我需要另想他法。
4.我的最终解决方案
接下来说下我最终想到的方便且容易上手的解决方案:那就是采用http工具执行url -> 然后把文件先下载到项目所在服务器的临时目录内 -> 然后再以读取普通文件路径的方式加载成File -> 再然后以流的方式输出给客户端弹窗另存为保存 -> 最后关闭流并删除服务器路径下的临时文件。
pom.xml
org.apache.poi poi-ooxml 3.17 org.apache.httpcomponents httpclient 4.4.1 cn.hutool hutool-all 5.7.17 前端js代码
//批量管理-下载批量导入数据 function downloadBatchImportDataTaskActionColumn(taskId) { var language = 'zh'; if(Cookies.get("language") != null && Cookies.get("language") != "") { language = Cookies.get("language") ; } var url = prefix + "/downloadBatchImportData?language=" + language; var form = $("
").attr("action", url).attr("method", "post"); form.append($("").attr("type", "hidden").attr("name", "taskId").attr("value", taskId)); form.appendTo('body').submit().remove(); }后端Controller代码
/** * 下载批量导入数据 * 流程: * 查询数据库判断filedownLink字段是否为空 * 为空:则代表旧数据,没有gofd对应的下载文件地址,因此把模板文件返回给客户端 * 不为空:则代表gofd已经上传了对应的批量导入文件,且数据库中保存地址链接 * 通过filedownLink封装成FiLE * 判断File在临时目录内是否存在 * 存在:则直接返回给客户端,最后再把服务器临时目录内文件删除 * 不存在:则通过http工具调用filedownLink封装成File,将文件写入tempFilePath临时目录内,再把文件File返回给客户端,最后再把服务器临时目录内文件删除 * @param req req * @param response response */ @RequestMapping(value = "/downloadBatchImportData") public void downloadBatchImportData(HttpServletRequest req, HttpServletResponse response) { logger.info("-downloadBatchImportData-begin"); String taskId = req.getParameter("taskId"); OutputStream os = null; InputStream io = null; String tempFilePath = TEMP_FILE_PATH; String fileName = ""; String language = req.getParameter("language"); Workbook wb = null; try { ImpExpTaskDetail impExpTaskDetail = isvcBatchTaskServiceMicro.selectTaskDetailByTaskId(taskId); String filedownLink = impExpTaskDetail.getLink(); if (org.springframework.util.StringUtils.isEmpty(filedownLink)) { fileName = MessageUtils.message("batch.template") + ".xlsx"; String templateFileName = BatchConstant.DOWNAD_TEMPLATE_NAME + "_" + language + BatchConstant.EXTENSION_XLSX; SysUser sysUser = ShiroUtils.getSysUser(); logger.info("-downloadBatchImportData-taskId:{},language:{}", taskId, language); if (isysUserService.get36kType(sysUser.getUserId()) == Poc36kEnum.POC6K.getType()) { templateFileName = BatchConstant.DOWNAD_TEMPLATE_NAME + "6k" + "_" + language + BatchConstant.EXTENSION_XLSX; } File templateFile = org.springframework.util.ResourceUtils.getFile("classpath:" + templateFileName); logger.info("-Template file exist!,templateFileName:{}", templateFileName); io = new FileInputStream(templateFile); wb = new XSSFWorkbook(io); } else { fileName = StringUtils.subscribeNameString(filedownLink); File file = ResourceUtils.getFile(String.join(File.separator, tempFilePath, fileName)); if (!file.exists()) { String begin = DateUtil.now(); DateTime beginTime = DateUtil.parse(begin); long download = HttpUtil.downloadFile(filedownLink, FileUtil.file(tempFilePath, fileName), new StreamProgress() { @Override public void start() { logger.info("开始下载,时间为:" + begin); } @Override public void progress(long progressSize) { logger.info("已下载:{}", FileUtil.readableFileSize(progressSize)); } @Override public void finish() { String end = DateUtil.now(); DateTime endTime = DateUtil.parse(end); long between = DateUtil.between(beginTime, endTime, DateUnit.MS); logger.info("下载完成,用时:" + DateUtil.formatBetween(between, BetweenFormatter.Level.SECOND)); } }); } io = new FileInputStream(file); wb = new XSSFWorkbook(io); } logger.info("-tempFilePath:{},fileName:{}", tempFilePath, fileName); response.setContentType("application/octet-stream;charset=UTF-8"); response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); wb.write(response.getOutputStream()); } catch (IOException e) { logger.error("-downloadBatchImportData error:{}", e.getMessage()); } finally { if (os != null) { try { os.close(); } catch (IOException e) { logger.error("-OutputStream error:{}", e.getMessage()); } } if (io != null) { try { io.close(); } catch (IOException e) { logger.error("-InputStream error:{}", e.getMessage()); } } if (Optional.ofNullable(tempFilePath).isPresent()) { // 强制删除临时文件 boolean isDelete = com.hytalk.util.FileUtil.delFile(new File(tempFilePath)); logger.info("-downloadBatchImportData 强制删除临时文件 , filePath: {} , isDelete : {} ", tempFilePath, isDelete); } } }
FileUtil工具类
import java.io.File; /** * 文件工具 * @Author 211145187 * @Date 2023/4/19 14:27 **/ public class FileUtil { /** * 删除文件 * @param file 文件 * @return boolean */ public static boolean delFile(File file) { if (!file.exists()) { return false; } if (file.isDirectory()) { File[] files = file.listFiles(); for (File f : files) { delFile(f); } } return file.delete(); } }
StringUtils工具类
/** * 字符串工具 * @author 211145187 * @Date: 2021/11/11 16:11 **/ public class StringUtils {/** * 截取url地址中的名称,比如路径地址为“http://10.110.38.253:11014/group1/batchImportData/组 (26).xlsx”,最后截取的名称为“组 (26).xlsx” * @param str 原字符串 * @return 截取后的字符串 */ public static String subscribeNameString(String str) { if (str.lastIndexOf("/") > -1) { str = str.substring(str.lastIndexOf("/") + 1); } return str; } }
说明:
只在意我的思路流程即可,至于工具类或者查数据库数据代码啥的就不复制粘贴了。