文件下载的写法
private void download(String token, String guid, HttpServletRequest req, HttpServletResponse resp) { File outputFile = null; try { EdmConfig config = getEdmConfig(token); // 请求参数类 ExcelTaskRequestVO requestVO = new ExcelTaskRequestVO(); UserVO user = (UserVO) RequestContext.getCurrent().getUser(); // 当前用户id requestVO.setUserId(String.valueOf(user.getUserId())); // 创建人 requestVO.setCreatedBy(user.getUserAccount()); // Excel引擎访问地址 requestVO.setServiceUrl(edmEndPoint); // 导出任务的GUID requestVO.setGuid(guid); EdmExcelClient excelClient = new EdmExcelClient(config); int times = 0; // 防止无限循环 String edmStatus = getEdmStatus(excelClient, requestVO); while (times < 10 && !"FINISH".equals(edmStatus)) { try { Thread.sleep(500); LOGGER.info("sleep 500 millisecond for download finish"); } catch (InterruptedException e) { LOGGER.info("sleep download finish InterruptedException:", e); } times++; edmStatus = getEdmStatus(excelClient, requestVO); } ResponseObject responseObject = excelClient.download(requestVO); if (responseObject != null && responseObject.getStatus() == 200) { Headers headers = responseObject.getResponseHeaders(); if (headers == null) { LOGGER.error("-------------------headers == null-------------------"); return; } String contentType = headers.get("Content-Type"); if ("application/json;charset=UTF-8".equals(contentType)) { LOGGER.debug("do nothing"); // JSON反序列化 } else if ("application/octet-stream;charset=UTF-8".equals(contentType)) { // 方式一:不经过服务器,但是文件名改不了 /* * resp.setContentType("application/octet-stream"); * String disposition = responseObject.getResponseHeaders().get("Content-Disposition"); * Pattern pattern = Pattern.compile("attachment;filename=(.*?)$", Pattern.CASE_INSENSITIVE); * Matcher matcher = pattern.matcher(disposition); * if (matcher.find()) { * String filename = URLDecoder.decode(matcher.group(1), CharsetNames.CS_UTF8); * resp.setHeader("Content-Disposition", "attachment;filename=" + filename); * } * resp.setCharacterEncoding(CharsetNames.CS_UTF8); * InputStream input = responseObject.getByteStream(); * OutputStream output = resp.getOutputStream(); * StreamUtil.transfer(input, output); */ // 方式二:先存到服务器再下载,这个中文文件名会乱码 FileInfoVO fileInfoVO = new FileInfoVO(); String disposition = responseObject.getResponseHeaders().get("Content-Disposition"); Pattern pattern = Pattern.compile("attachment;filename=(.*?)$", Pattern.CASE_INSENSITIVE); if (disposition != null) { Matcher matcher = pattern.matcher(disposition); if (matcher.find()) { String filename = URLDecoder.decode(matcher.group(1), CharsetNames.CS_UTF8); fileInfoVO.setDisplayName(filename); String outputFilePath = System.getProperty("java.io.tmpdir") + filename; String checkOutputFilePath = StringVerifyUtil.dealSpecialChar(outputFilePath); outputFile = new File(checkOutputFilePath); IOUtils.copyTo(responseObject.getByteStream(), outputFile.getCanonicalPath(), 1024); // just for cloud dragon setFileInfoVo(outputFile, fileInfoVO); } } downloadOutput(req, resp, fileInfoVO); } } } catch (EdmException | IOException | DownloadException e) { LOGGER.error("download error:", e); } finally { if (outputFile != null) { boolean delFlag = outputFile.delete(); if (!delFlag) { LOGGER.info("outputFile delete failed"); } } } } private void setFileInfoVo(File outputFile, FileInfoVO fileInfoVo) { InputStream in = null; try { File checkFile = StringVerifyUtil.checkFilePath(outputFile); in = new FileInputStream(checkFile); final ByteArrayOutputStream baoS = new ByteArrayOutputStream(); final byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) > -1) { baoS.write(buffer, 0, len); } baoS.flush(); fileInfoVo.setInputStream(new ByteArrayInputStream(baoS.toByteArray())); fileInfoVo.setStream(true); } catch (IOException e) { LOGGER.info("IOException ", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } } } } private void downloadOutput(HttpServletRequest req, HttpServletResponse resp, FileInfoVO file) throws DownloadException { InputStream in = null; OutputStream out = null; try { // 尝试下载文件 // 根据浏览器判断下载文件名转义 wx244051 2016-01-14 String agent = req.getHeader("User-Agent").toLowerCase(); in = file.getInputStream(); if (in != null) { if (agent.contains("msie") || agent.contains("trident")) { download.outputFromStream(req, resp, in, file.getDisplayName(), true, 0L); } else { download.outputFromStream(req, resp, in, new String(file.getDisplayName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1), false, 0L); } } } catch (FileNotFoundException e) { LOGGER.error("mkpVerticalPrice file not found -- ", e); throw new DownloadException("honor.jalor5.download.support.00010002"); } catch (Exception e) { LOGGER.error("mkpVerticalPrice download error -- ", e); throw new DownloadException("honor.jalor5.download.support.00010001"); } finally { StreamUtil.closeStreams(in, out); } }
private void downloadExcel(HttpServletRequest req, HttpServletResponse resp, File file) { InputStream in = null; DownloadOutput download = new DownloadOutput(); try { // 尝试下载文件 // 根据浏览器判断下载文件名转义 String agent = req.getHeader("User-Agent").toLowerCase(); File checkFile = StringVerifyUtil.getValidDirectoryPath(file); in = new FileInputStream(checkFile); if (agent.contains("msie") || agent.contains("trident")) { download.outputFromStream(req, resp, in, file.getName(), true, 0L); } else { download.outputFromStream(req, resp, in, new String(file.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1), false, 0L); } } catch (FileNotFoundException e) { LOGGER.error("Price Authorization Letter file not found -- ", e); } catch (Exception e) { LOGGER.error("Price Authorization Letter download error -- ", e); } finally { StreamUtil.closeStreams(in); if (in != null) { try { in.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } } } if (file.delete()) { LOGGER.info("Price Authorization Letter tmp file delete success -- "); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix