java下载接口
@PostMapping(value = "/download") public void download(@RequestBody DownloadReq req, HttpServletRequest request, HttpServletResponse response) { // 省略.......... String path = new File(path).getAbsolutePath() + File.separator + req.getFileName(); File file = new File(path); if (!file.exists()) { LOGGER.info("file:{}", file.getAbsolutePath()); LOGGER.info("下载文件不存在"); } response.reset(); response.setContentType("application/octet-stream"); response.setCharacterEncoding("utf-8"); response.setContentLength((int) file.length()); String fileInfoHear = String.format("attachment;filename=%s", req.getFileName()); response.addHeader("Content-Disposition", fileInfoHear); String origin = request.getHeader("Origin"); response.addHeader("Access-Control-Allow-Origin", origin); response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); response.addHeader("Access-Control-Allow-Headers", "Content-Type"); response.addHeader("Access-Control-Allow-Credentials", "true"); // 让浏览器能访问到其它响应头 response.addHeader("Access-Control-Expose-Headers","Content-Disposition"); try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) { byte[] buff = new byte[1024]; OutputStream os = response.getOutputStream(); int i = 0; while ((i = bis.read(buff)) != -1) { os.write(buff, 0, i); os.flush(); } LOGGER.info("file:{}, 下载成功", file.getAbsolutePath()); } catch (IOException e) { LOGGER.error("异常", e); } // 只能返回null 或者方法是void, 否则会导致下载流关闭 }
java调用下载接口
public void download(DownloadReq req, String targetPath) { Map<String, Object> params = new HashMap<>(); params.put("id", req.getId()); Path targetPathO = Paths.get(targetPath); //定义请求头的接收类型 RequestCallback requestCallback = request -> { request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)); // json参数 request.getHeaders().setContentType(MediaType.APPLICATION_JSON); request.getBody().write(JSON.toJSONString(params).getBytes()); }; ResponseExtractor<Void> responseExtractor = response -> { //对响应进行流式处理而不是将其全部加载到内存中 Files.copy(response.getBody(), targetPathO, StandardCopyOption.REPLACE_EXISTING); return null; }; // 省略代码..... restTemplate.execute(url, HttpMethod.POST, requestCallback, responseExtractor); log.info("下载文件:{}, 完成", req.getFileName()); }
前端调用下载接口
this.loading = true axios({ method: 'post', url: process.env.VUE_APP_BASE_API + '/download', data: { // json参数 id: this.$data.id }, responseType: 'blob', onDownloadProgress: (evt) => { // 对原生进度事件的处理, 会在浏览器下方弹出下载文件框 this.setState({ progress: parseInt((evt.loaded / evt.total) * 100) }); } }).then(response => { let contentDisposition = response.headers['content-disposition']; //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名; let filename = contentDisposition.split("filename=")[1]; // 将二进制流转为blob let data = response.data ; const blob = new Blob([data], { type: 'application/octet-stream' }) if (window.navigator.msSaveBlobOrOpenBlob) { // 兼容IE,window.navigator.msSaveBlob:以本地方式保存文件 window.navigator.msSaveBlob(blob, decodeURI(filename)) } else { // 创建新的URL并指向File对象或者Blob对象的地址 const blobURL = window.URL.createObjectURL(blob) // 创建a标签,用于跳转至下载链接 const tempLink = document.createElement('a') tempLink.style.display = 'none' tempLink.href = blobURL tempLink.setAttribute('download', decodeURI(filename)) // 兼容:某些浏览器不支持HTML5的download属性 if (typeof tempLink.download === 'undefined') { tempLink.setAttribute('target', '_blank') } // 挂载a标签 document.body.appendChild(tempLink) tempLink.click() document.body.removeChild(tempLink) // 释放blob URL地址 window.URL.revokeObjectURL(blobURL) } }).finally(() => { this.loading = false })