• spring boot + vue 前后端下载文件文件


    springboot返回文件两种方式

    第一种写入流中返回

    Response.setContentType(MIME)的作用是时客户端的浏览器区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
    MIME-Version:
    Content-Type:(常用。 该实体头的作用是让服务器告诉浏览器它发送的数据属于什么文件类型。)

    Content-Transfer-Encoding:

    Content-ID:

    Content-Disposition: (常用。 当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。

    原文链接:https://blog.csdn.net/u010405836/article/details/100767562

    获取当前程序(或类文件)所在的目录可以用以下3个方法(可能还有其他方法,后续会逐步添加):

        1、使用File类提供的方法来获取当前路径
    
        2、使用Class类的getResource("").getPath()获取当前.class文件所在的路径
    
        3、由System.getProperty("user.dir")获取当前程序的根目录
    

    ————————————————
    版权声明:本文为CSDN博主「Asuka_08」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/AsuKA_F/article/details/94488884
    文件预览
    后端方法1

        //    todo 文件预览
        @GetMapping(value = "/preview")
        public void download(String filePath, HttpServletResponse response) throws Exception {
    //        绝对路径 E:\code\experiment\back\formal\back-one
            System.out.println(System.getProperty("user.dir"));
            System.out.println(getClass().getResource("/"));
            System.out.println(filePath);
    //        读取的文件路径 filePath
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            byte[] bytes = IOUtils.toByteArray(in);
    
            response.setContentType("docx");
            response.setContentLength(bytes.length);
            response.setHeader("Content-Disposition", "attachment;filename=result");
            out = response.getOutputStream();
            out.write(bytes);
            out.close();
            in.close();
        }
    

    后端方法2

        @GetMapping("/download")
        @ResponseBody
        public void downloadFile(HttpServletRequest request, HttpServletResponse response, String filePath) throws IOException {
            String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
            out = response.getOutputStream();
            IOUtils.copy(in,out);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    
    word文件预览插件vue实现
      import {defaultOptions, renderAsync} from "docx-preview";
    
    
      <el-dialog
        id="container"
      :visible.sync="wordDialogVisible"
      >
    
      </el-dialog>
    
        <el-button @click="doTest">
          回归测绘师
        </el-button>
    
          doTest() {
            this.$axios({
              url: 'http://localhost:40822/api/XXX/cluster/download',
              method: 'get',
              params: {filePath: this.word},
              responseType: 'blob'
            }).then(res => {
              const blob = new Blob([res.data]);
              this.wordDialogVisible = true;
              renderAsync(blob, document.getElementById("container"))
            })
          },
    

    ###后端返回byte[]

        @GetMapping(value = "/preview")
        public byte[] preview(String filePath, HttpServletResponse response) throws Exception {
    
    
            System.out.println(filePath);
    //        读取的文件路径 filePath
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            byte[] bytes = IOUtils.toByteArray(in);
            response.setContentType("xlsx");
            response.setContentLength(bytes.length);
            response.setHeader("Content-Disposition", "attachment;filename=result");
            return  bytes;
        }
    

    前端下载 responseType: ‘arraybuffer’

         //method方法:
        handleExport() {
          this.$axios({
              url: 'http://localhost:40822/api/xjtu/multiRegression/preview',
              method: 'get',
              params: {filePath: this.excelPath},
              responseType: 'arraybuffer'
            }).then(res => {
              var fileName = "ress"
               const blob = new Blob([res.data]);
            let a = document.createElement("a"); //创建一个标签
            a.href = URL.createObjectURL(blob); // 将流文件写入a标签的href属性值
            a.download = fileName + ".xlsx"; //设置文件名
            a.style.display = "none"; // 障眼法藏起来a标签
            document.body.appendChild(a); // 将a标签追加到文档对象中
            a.click(); // 模拟点击了a标签,会触发a标签的href的读取,浏览器就会自动下载了
            a.remove(); // 一次性的,用完就删除a标签
          })
        },
    

    预览效果不理想,我想要有单元格的
    在这里插入图片描述

    第二 使用@GetMapping注解,指定返回格式

    预览excel

    前端

      import xlsx from "xlsx"
    
          previewXlsx(){
          this.$axios({
              url: 'http://localhost:40822/api/xjtu/multiRegression/preview',
              method: 'get',
              params: {filePath: this.excelPath},
              responseType: 'arraybuffer'
            }).then(res => {
              var fileName = "ress"
              var  XLSX = require("xlsx")
               const blob = new Blob([res.data]);
              let workbook =XLSX.read(new Uint8Array(res.data), { type: 'array' }); // 解析数据
            var worksheet = workbook.Sheets[workbook.SheetNames[0]]; // workbook.SheetNames 下存的是该文件每个工作表名字,这里取出第一个工作表
           this.tableHtml= XLSX.utils.sheet_to_html(worksheet); // 渲染
          })
            
          }
    
    

    后端

        //    //    todo 文件预览  excel
        @GetMapping(value = "/preview")
        public byte[] preview(String filePath, HttpServletResponse response) throws Exception {
            System.out.println(filePath);
    //        读取的文件路径 filePath
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            byte[] bytes = IOUtils.toByteArray(in);
            response.setContentType("xlsx");
            response.setContentLength(bytes.length);
            response.setHeader("Content-Disposition", "attachment;filename=result");
            return  bytes;
        }
    

    前端下载三种文件

    第一种方式是前端创建超链接

    通过a标签的链接向后端服务发get请求,接收后端的文件流,非常简单:

    <a :href='"http://localhost:40822/api/XXX/cluster/downloadA"' >下载模板</a>
    

    另一种情况是创建,动态创建a标签:

    <el-button id="download" @click="downloadFile">下载文件</el-button>
    
          downloadFile(){
            let a = document.createElement('a')
            a.href = 'http://localhost:40822/api/XXX/cluster/downloadA'
            a.click();
          },
    

    后端

        @GetMapping("/downloadA")
        @ResponseBody
        public void downloadFileA(HttpServletResponse response) throws IOException {
            String filePath = "D:\\data\\StatisticalAnalysis\\1\\2022-08-27\\output\\word.docx";
            String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
            out = response.getOutputStream();
            IOUtils.copy(in,out);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    

    第二种方式通过创建iframe的方式()

    我的路径参数含有地址,所以后端解析出错,
    地址是:word: ‘D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx’,

    java.lang.IllegalArgumentException: Invalid character found in the request target [/api/xjtu/cluster/downloadA?filePath=D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx]. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:490) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.AbstractProtocol C o n n e c t i o n H a n d l e r . p r o c e s s ( A b s t r a c t P r o t o c o l . j a v a : 888 ) [ t o m c a t − e m b e d − c o r e − 9.0.41. j a r : 9.0.41 ] a t o r g . a p a c h e . t o m c a t . u t i l . n e t . N i o E n d p o i n t ConnectionHandler.process(AbstractProtocol.java:888) [tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.NioEndpoint ConnectionHandler.process(AbstractProtocol.java:888)[tomcatembedcore9.0.41.jar:9.0.41]atorg.apache.tomcat.util.net.NioEndpointSocketProcessor.doRun(NioEndpoint.java:1597) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor W o r k e r . r u n ( T h r e a d P o o l E x e c u t o r . j a v a : 617 ) [ n a : 1.8. 0 1 31 ] a t o r g . a p a c h e . t o m c a t . u t i l . t h r e a d s . T a s k T h r e a d Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131] at org.apache.tomcat.util.threads.TaskThread Worker.run(ThreadPoolExecutor.java:617)[na:1.8.0131]atorg.apache.tomcat.util.threads.TaskThreadWrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]

    <el-button  size="mini"  type="primary" icon="el-icon-download" @click="handleExport">导出</el-button>
    
    data 数据
    word: 'D:\\data\\StatisticalAnalysis\\1\\2022-08-27\\output\\word.docx',
    
         //method方法:
        handleExport() {
    
          var elemIF = document.createElement('iframe')
          elemIF.src = 'http://localhost:40822/api/xjtu/cluster/downloadA?filePath=' + this.word
          elemIF.style.display = 'none'
          document.body.appendChild(elemIF)
        },
    
        @GetMapping("/downloadA/{filePath}")
        @ResponseBody
        public void downloadFileA(HttpServletResponse response ,@PathVariable("filePath") String filePath)   throws IOException {
            System.out.println(filePath);
            String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
            FileInputStream in = null;
            ServletOutputStream out = null;
            in = new FileInputStream(filePath);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
            out = response.getOutputStream();
            IOUtils.copy(in,out);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    

    第三种方式,会对后端发的post请求,使用blob格式

    参考博客

    前端向后端传递参数 data: {filePath: this.word},其中word: ‘D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx’,因为这个word是个路径含有\ - 这种符号,前端会对这些进行编码
    需要使用 encodeuricomponent

    https://www.cnblogs.com/webSnow/p/15307306.html

  • 相关阅读:
    java算法第21天 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先
    Android 系统的异常信息捕获
    Javascript真的是10天内做出来的吗?
    JWFD开源工作流矩阵引擎-遍历算法第二次修正代码
    PMP每日一练 | 考试不迷路-8.17(包含敏捷+多选)
    LEETCODE力扣详解:7.整数反转;9.回文数
    Qt Creator 编译 libxlsxwriter
    线性表重点操作代码集锦
    标签类目体系(面向业务的数据资产设计方法论)-读书笔记2
    MyBatis 源码分析之 Mapper 接口代理对象生成及方法执行
  • 原文地址:https://blog.csdn.net/weixin_42382758/article/details/126562741