• VUE:前端下载Excel模板文件


    一、效果

    点击“模板按钮”,就开始下载

    二、根据磁盘路径下载

    1、前端代码

    1、template

    <el-button
            type="primary"
            icon="el-icon-download"
            @click="downloadTemplate('药材信息-模板.xlsx')">下载模板</el-button>

    2、在main.js中注册原型方法

    Vue.prototype.downloadTemplate = function(templateName) {
      const fileEntity = {
        fileName: templateName, // 文件名称
        filePath: globalProperties.importTemplate + templateName, // 文件路径
        downloadChannel: 'DIR' // 下载类型
      }
      baseAPI.ptsFileDownload(fileEntity).then(response => {
        fileDownload(response, templateName)
      }).catch(error => {
        console.log(error)
      })
    }

    注意:fileDownload中第一个参数是reponse还是response.data,要看拦截器中返回的是啥。如果返回的是resonse,则fileDownload中第一个参数为response.data。

    如果response拦截器中返回的是response.data,那么fileDownload方法的第一个参数为response,而不是response.data。

    // response 拦截器
    service.interceptors.response.use(res => {
        const headers = res.headers
        // 此类为下载流文件,不拦截
        if (headers['content-type'] === 'application/octet-stream') {
            return res
        }
        if (headers['content-type'] === 'arrayBuffer;charset=UTF-8') {
            return res
        }
        var data = res.data;
        return data;
    },err =>{
        console.log(err)
    });

    当content-type为application/octet-stream时,放行。

    3、在global.js中指定Excel模板的位置

    const globalProperties = {
      importTemplate: 'D:\\upload\\template\\'
    }

    在该位置添加Excel模板

    在main.js中引入global.js

    import './global.js'

    4、安装并引入js-file-download

    安装

    npm install js-file-download

    main.js中引入

    import fileDownload from 'js-file-download'

    5、baseAPI.js

    import request from '@/utils/request'
    
    export const baseAPI = {
    
      ptsFileDownload(query) {
        return request({
          url: '/fileServer/fileDownload',
          method: 'post',
          data: query,
          responseType: 'arraybuffer'
        })
      },
    }

    在main.js中引入baseAPI.js

    import { baseAPI } from '@/api/base/baseAPI'

    2、后台代码

    下载的流程是:先读文件,在创建一个临时文件,再下载。

    controller

    @Controller
    @RequestMapping("api/fileServer")
    public class PtsFileController {    
        @Autowired
        private PtsFileService ptsFileService;
    
        @RequestMapping(value = "/fileDownload", method = { RequestMethod.POST, RequestMethod.GET })
        public String fileDownload(@RequestBody(required=true)PtsFileEntity fileEntity, HttpServletResponse response) throws Exception {
            ptsFileService.fileDownload(fileEntity, response);
            return null;
        }
    }

    service

    @Service
    public class PtsFileService {
        private static Logger logger = LoggerFactory.getLogger(PtsFileService.class);
        private static final String CHANNEL_DIR = "DIR"; // 根据文件的磁盘位置下载,如/usr/template/
        private static final String CHANNEL_URL = "URL"; // 根据URL下载,如http://...
    
        /**
         * 文件下载service入口
         *
         * @param fileEntity
         * @param response
         * @throws Exception
         */
        public void fileDownload(PtsFileEntity fileEntity, HttpServletResponse response) throws Exception {
            String fileName = fileEntity.getFileName();
            if (null == fileName || ("").equals(fileName.trim())) {
                logger.error("No FileName Found.");
                throw new Exception("No FileName Found.");
            }
            String downloadChannel = fileEntity.getDownloadChannel();
            if (null == downloadChannel || ("").equals(downloadChannel.trim())) {
                logger.error("Need to identity download channel.");
                throw new Exception("Need to identity download channel.");
            }
            if (CHANNEL_DIR.equalsIgnoreCase(downloadChannel)) {
                this.downloadFromDir(fileEntity, response);
            } else if (CHANNEL_URL.equalsIgnoreCase(downloadChannel)) {
                this.downloadFromUrl(fileEntity, response);
            }
        }
    
        /**
         * 从URL地址下载
         *
         * @param fileEntity
         * @param response
         * @throws Exception
         */
        private void downloadFromUrl(PtsFileEntity fileEntity, HttpServletResponse response) throws Exception {
            String filePath = fileEntity.getFilePath();
            String serverFilePath = fileEntity.getServerFilePath();
            if ((null == filePath || ("").equals(filePath.trim())) && (null == serverFilePath || ("").equals(serverFilePath.trim()))) {
                logger.error("No FilePath Found.");
                throw new Exception("No FilePath Found.");
            }
            String realFilePath = (null == filePath || ("").equals(filePath.trim())) ? serverFilePath : filePath;
            logger.info("Begin download file from Url: " + realFilePath);
    
            try {
                URL url = new URL(realFilePath);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //设置超时间为3秒
                conn.setConnectTimeout(3 * 1000);
                //防止屏蔽程序抓取而返回403错误
                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
    
                //得到输入流
                InputStream inputStream = conn.getInputStream();
                //获取自己数组
                byte[] srcBytes = readInputStream(inputStream);
                this.createTempFile(fileEntity, srcBytes);
                this.download(fileEntity, response);
            } catch (IOException e) {
                e.printStackTrace();
                throw new Exception(e);
            }
        }
    
        /**
         * 从服务器路径下载
         *
         * @param fileEntity
         * @param response
         * @throws Exception
         */
        public void downloadFromDir(PtsFileEntity fileEntity, HttpServletResponse response) throws Exception {
            String filePath = fileEntity.getFilePath();
            String serverFilePath = fileEntity.getServerFilePath();
            if ((null == filePath || ("").equals(filePath.trim())) && (null == serverFilePath || ("").equals(serverFilePath.trim()))) {
                logger.error("No FilePath Found.");
                throw new Exception("No FilePath Found.");
            }
            String realFilePath = (null == filePath || ("").equals(filePath.trim())) ? serverFilePath : filePath;
            logger.info("Begin download file from Directory: " + realFilePath);
    
            try {
                // 以流的形式下载文件。
                InputStream fis;
                fis = new BufferedInputStream(new FileInputStream(realFilePath));
                byte[] srcBytes = new byte[fis.available()]; // 读取文件到字节数组中
                fis.read(srcBytes);
                fis.close();
    
                this.createTempFile(fileEntity, srcBytes); // 将字节数组中的内容存入临时文件中
                this.download(fileEntity, response); // 将临时文件内容读到字节数组中,再将字节数组中的内容写入输出流
            } catch (IOException ex) {
                ex.printStackTrace();
                throw new Exception(ex);
            }
        }
    
        /**
         * 创建临时文件
         *
         * @param fileEntity
         * @param srcBytes
         */
        public void createTempFile(PtsFileEntity fileEntity, byte[] srcBytes) throws Exception {
            byte[] targetBytes = srcBytes;
    
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String rootPath = this.getClass().getResource("/").getPath(); // /D:/project/prism/myProject/springboot-zwh/target/classes/
            String path1 = rootPath + "/download_files/";
            File exportPath1 = new File(path1);
            if (!exportPath1.exists()) exportPath1.mkdir();
            String path2 = path1 + simpleDateFormat.format(new Date());
            File exportPath2 = new File(path2);
            if (!exportPath2.exists()) exportPath2.mkdir();
            String fileDirPath = path2 + "/" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString() + fileEntity.getFileName();
            File file = new File(fileDirPath);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(targetBytes);
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                throw new Exception(ex);
            }
    
            fileEntity.setRealFilePath(fileDirPath);
        }
    
        /**
         * 拼接response header 并已流的形式下载文件
         *
         * @param fileEntity
         * @param response
         * @throws Exception
         */
        public void download(PtsFileEntity fileEntity, HttpServletResponse response) throws Exception {
            String fileName = fileEntity.getFileName();
            String realFilePath = fileEntity.getRealFilePath(); // 将临时路径中的文件
            File file = new File(realFilePath);
    
            try {
                // 以流的形式下载文件。
                InputStream fis;
                fis = new BufferedInputStream(new FileInputStream(realFilePath));
                byte[] srcBytes = new byte[fis.available()];
                fis.read(srcBytes);
                fis.close();
    
                // 清空response
                response.reset();
                // 设置response的Header
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                response.setCharacterEncoding("utf-8");//设置编码集,文件名不会发生中文乱码
    
                response.setContentType("application/force-download");//
                response.setHeader("content-type", "application/octet-stream");
                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(), "utf-8"));// 设置文件名
                response.addHeader("Content-Length", "" + file.length());
                response.setHeader("Access-Control-Allow-Origin", "*");
                OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
                toClient.write(srcBytes);
                toClient.flush();
                toClient.close();
            } catch (IOException ex) {
                throw new Exception(ex);
            }
        }
    
        /**
         * 从输入流中获取字节数组
         *
         * @param inputStream
         * @return
         * @throws IOException
         */
        public static byte[] readInputStream(InputStream inputStream) throws IOException {
            byte[] buffer = new byte[1024];
            int len = 0;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while ((len = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            bos.close();
            return bos.toByteArray();
        }
    }

    临时文件的存储位置:

    三、根据URL下载

    1、前端代码

    template

    <el-button class="el-button el-button&#45;&#45;primary el-button&#45;&#45;small" type="primary" @click="downLoadTest">下载测试
            </el-button>

    引入baseAPI

    import { baseAPI } from '@/api/base/baseAPI'

    script

    downLoadTest() {
          const fileName = '阿里巴巴Java开发手册.pdf'
          const filePath = 'http://localhost:8888/template/阿里巴巴Java开发手册.pdf'//
          const fileEntity = {
            fileName: fileName,
            filePath: filePath,
            downloadChannel: 'URL' // DIR
          }
          baseAPI.ptsFileDownload(fileEntity).then(response => {
            console.info(response)
            fileDownload(response, fileName)
          }).catch(error => {
            console.log(error)
          })
        }

    注意:fileDownload的第一个参数为response,因为响应拦截器中已经取出了data,如下所示

    // response 拦截器
    service.interceptors.response.use(res => {
        const headers = res.headers
        // 此类为下载流文件,不拦截
        if (headers['content-type'] === 'application/octet-stream') {
            return res
        }
        if (headers['content-type'] === 'arrayBuffer;charset=UTF-8') {
            return res
        }
        var data = res.data;
        return data;
    },err =>{
        console.log(err)
    });

    在本地测试时,使用nginx代理。

    后台代码与上相同。

  • 相关阅读:
    省市区(简版)
    利用 NSSortDescriptor 对 NSMutableArray 排序
    Objective-C 高性能的循环遍历 forin
    iOS-内存管理
    ios-遍历和排序
    寒假 OC-代理,类目,内存,协议,延展,数组,字典,集合
    Oracle SQL篇(二)oracle自连接操作
    Oracle SQL篇(三)Oracle ROWNUM 与TOP N分析
    Oracle SQL篇(四)group by 分组与分组的加强 rollup
    ODI中删除数据的处理
  • 原文地址:https://www.cnblogs.com/zwh0910/p/16085514.html
Copyright © 2020-2023  润新知