java怎么打包成apk(Java-如何打包下载成.zip文件)
打包下载成.zip文件
项目背景
公司使用vue + SpringBoot
实现批量下载功能
今天在调试批量下载这个功能 。打包成.zip文件时 ,在返回给前端浏览器出现报错信息:
后端报错:ERROR c.c.p.c.e.BusinessExceptionHandler - java.io.IOException: 你的主机中的软件中止了一个已建立的连接 。
org.apache.catalina.connector.ClientAbortException: java.io.IOException: 你的主机中的软件中止了一个已建立的连接 。找了好久的错 ,发现浏览器的控制台有报错信息
Access to XMLHttpRequest at http://...:8097/pcsms-admin/batchExport/pdf?vids=1e7ed541bdd6b9f5614cca14623f8681,8dfda9f7151745ad5aa5f0abc2c55d5c from origin http://..:8001 has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource.
于是在后端中设置响应体 ,如 HttpServletResponse response :
response.setHeader("Access-Control-Allow-Origin","*");紧接着又出现如下的报错信息:
Access to XMLHttpRequest at http://...:8097/batchExport/pdf?vids=1e7ed541bdd6b9f5614cca14623f8681,8dfda9f7151745ad5aa5f0abc2c55d5c from origin http://...:8001 has been blocked by CORS policy: The value of the Access-Control-Allow-Origin header in the response must not be the wildcard * when the requests credentials mode is include. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
在面向百度编程中 ,找到一个帖子有详细的解释--axios设置withCredentials导致“跨域 ”的解决方案 。检查前端配置果然有:
axios.defaults.withCredentials = true;
(一) 当前端配置withCredentials=true时, 后端配置Access-Control-Allow-Origin不能为*, 必须是相应地址
(二) 当配置withCredentials=true时, 后端需配置Access-Control-Allow-Credentials
(三) 当前端配置请求头时, 后端需要配置Access-Control-Allow-Headers为对应的请求头集合于是我们可以采取方法一:axios.defaults.withCredentials = false;
在找其他解决方法时 ,找到一个可以不更改前端配置的方法二--Jquery Ajax设置withCredentials解决跨域请求 ,在response里加上以下两个header
response.addHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); response.addHeader("Access-Control-Allow-Credentials","true");最后 ,终于问题成功解决 。
后端代码:
TestController @RequestMapping(value = "/batchExport/pdf", method = RequestMethod.POST) public void batchExportPdf(HttpServletRequest request, HttpServletResponse response, @RequestParam("vids") String vids) throws Exception { //获取uavFileId ,不进行xss过滤 // HttpServletRequest orgRequest = XssHttpServletRequestWrapper.getOrgRequest(request); // String ids = orgRequest.getParameter("vids"); String[] vid = vids.split(","); byte[] data = sopService.batchExportPdf(vid); String fileName = URLEncoder.encode("批量下载PDF" + DateUtils.format(new Date(), "yyyyMMddHHmmss") + ".zip", "UTF-8"); response.reset(); // 当前端配置withCredentials=true时, 后端配置Access-Control-Allow-Origin不能为*, 必须是相应地址 response.addHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // 这个若不起作用 ,使用下面的"FileName"的 // response.addHeader("Access-Control-Expose-Headers","*"); response.addHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE"); // 设置在下载框默认显示的文件名 response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8" + fileName); response.setHeader("FileName", fileName); // 让axios放行指定的响应头 https://blog.csdn.net/u012586326/article/details/125790079 response.addHeader("Access-Control-Expose-Headers","FileName"); // 写明文件大小 response.addHeader("Content-Length", "" + data.length); // 指明response的返回对象是文件流 response.setContentType("application/octet-stream; charset=UTF-8"); response.setCharacterEncoding("UTF-8"); // 当前端配置withCredentials=true时, 后端需配置Access-Control-Allow-Credentials response.addHeader("Access-Control-Allow-Credentials","true"); IOUtils.write(data, response.getOutputStream()); } TestService /** * 批量下载pdf * @param vids * @return */ byte[] batchExportPdf(String[] vids) throws Exception; TestServiceImpl @Override public byte[] batchExportPdf(String[] vids) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // 用于将数据压缩成Zip文件格式 ZipOutputStream zipOut = new ZipOutputStream(outputStream); FileInputStream inputStream = null; List<String> deletePdf = new ArrayList<>(); List<FileInputStream> in = new ArrayList<>(); try { for (String vid : vids) { // 下载到本地 // PdfDTO包含:pdfPath(本地PDF路径) 、fileName(下载后的文件名(不含文件后缀.pdf)) PdfDTO dto = exportPdfByVid(vid); if (!ObjectUtils.isEmpty(dto)) { zipOut.putNextEntry(new ZipEntry((Objects.requireNonNull(dto.getFileName())) + ".pdf")); inputStream = new FileInputStream(new File(dto.getPdfPath())); int len; byte[] bytes = new byte[1024]; while ((len = inputStream.read(bytes)) != -1) { zipOut.write(bytes, 0, len); } //关闭该zip文件中打开的项 zipOut.closeEntry(); deletePdf.add(dto.getPdfPath()); in.add(inputStream); } } } catch (Exception e) { log.error("批量下载时出现错误:" + e.toString()); throw new BusinessException("批量下载时出现错误:" + e.getMessage()); } finally { try { for (FileInputStream stream : in) { stream.close(); } // 关流 IOUtils.closeQuietly(zipOut); } catch (IOException e) { log.error("批量下载时流关闭异常:" + e.toString()); } // 删除源文件(我这里是因为从数据服务器下载了文件到本地 ,所以删掉本地的) File file = null; for (String s : deletePdf) { file = new File(s); file.delete(); } } return outputStream.toByteArray(); }参考:
https://blog.csdn.net/cckevincyh/article/details/81140443
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
https://blog.csdn.net/baidu_28068985/article/details/105558280
https://blog.csdn.net/HermitSun/article/details/100797223创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!