Vue はファイル ストリームをエクスポートして添付ファイル名を取得し、ダウンロードします (response.headers でエクスポートされたファイル名を解析します)。

必要

  之前实现的导出都是各自的业务层,调用接口,使用blob对象转换,最终a标签导出,需要自定义文件名跟文件后缀。
  现在统一在拦截器配置,根据后端返回的response.headers解析是否是文件流,统一做配置处理,然后对后端返回的filename进行转码,后端统一配置文件名及类型。前端只管a标签下载即可。

これまでに実装したメソッド(各ビジネス層の記述メソッド)

//数据导出
    indexExport() {
    
    
      let statYear = {
    
    
        statDate: this.form.statDate,
        dataType: "1",
      };
      let infoMsg = this.$notify.info({
    
    
        title: "消息",
        message: "正在下载文件,勿退出,请稍后",
        duration: 0,
      });
      gljyjcDataExport(statYear).then((res) => {
    
    
        infoMsg.close(); //下载成功,等待下载提示框关闭
        this.$notify({
    
    
          title: "成功",
          message: "下载完成",
          type: "success",
        });
        let blob = new Blob([res], {
    
    
          type: "",
        });
        let url = window.URL.createObjectURL(blob);
        const link = document.createElement("a"); // 创建a标签
        link.href = url;
        link.download = "数据清单(" + this.form.statDate + ").xlsx"; // 重命名文件
        link.click();
        URL.revokeObjectURL(url); // 释放内存
      });
    },

現在実装している方法(axiosでのインターセプタの設定処理を統一)

バックエンドがストリーム ファイルを返すときに送信される response.headers には Content-Disposition フィールドがあるため、主にコメント行「File Download」に注目してください。ファイル名を取得した後、ファイル名に含まれる情報を
decodeURIComponent にトランスコードすると decodeURI がトランスコードできます 両者の違いは何ですか? レベルが限られていてわかりません 一致するオプションを確認できます百度で。

//拦截器里肯定有请求拦截代码axios.interceptors.request。怕展示代码冗余就不多贴了
...
axios.interceptors.response.use(
    response => {
    
    
    
        const res = response.data;
        const config = response.config;
        console.log(response.headers,"response.headers")//这块可以看一下response.headers究竟是什么
        // 文件下载(主要看这块)
        if (response.headers['content-disposition']) {
    
    
            let downLoadMark = response.headers['content-disposition'].split(';');
            if (downLoadMark[0] === 'attachment') {
    
    
                // 执行下载
                let fileName = downLoadMark[1].split('filename=')[1];
                if (fileName) {
    
    
                    //fileName = decodeURIComponent(filename);//对filename进行转码
                    fileName = decodeURI(fileName);
                    if (window.navigator.msSaveOrOpenBlob) {
    
    
                        navigator.msSaveBlob(new Blob([res]), fileName);
                    } else {
    
    
                        let url = window.URL.createObjectURL(new Blob([res]));
                        let link = document.createElement('a');
                        link.style.display = 'none';
                        link.href = url;
                        link.setAttribute('download', fileName);
                        document.body.appendChild(link);
                        link.click();
                        return;
                    }
                } else {
    
    
                    return res;
                }
            }
        }

        // 全局异常处理(获取code做正常的拦截操作,根据自己的业务层code写符合的就可)
        if (res.code !== CODE_SUCCESS) {
    
    
            if (res.code == '205') {
    
    
                Message.error({
    
     message: res.data || "登录失败" });
                store.dispatch("user/logout").then(() => {
    
    
                    window.location.reload();
                  });
                return
            }
            if (res.code === WARN_TIP) {
    
    
                Message.warning({
    
    
                    message: res.message
                });
            }

            if (res.code === LOGIN_FAIL) {
    
    
                Message.error({
    
     message: res.message || "登录失败" });
            }
            // 其他状态码特殊处理
            return Promise.reject(new Error(res.message || "Error"));
        }

        return res;
    }, error => {
    
    
        // 防重复提交
        if (error.message) {
    
    
            allowRequest(reqList, error.message.url);
        }
        if (error.response) {
    
    
            if (error.response.data.code == 600 && !tipCode) {
    
    
                tipCode = true;
                Message.error({
    
     message: '系统登录身份令牌失效,请重新登录!' });
            } else if (error.response.status == 500) {
    
    
                Message.error({
    
     message: '系统异常' });
            }
        }
        return Promise.reject(error);
    }
);

ここに画像の説明を挿入
ここに画像の説明を挿入

上記は解析される前にブラウザに表示されるフォルダ名ですが、
decodeURIComponent または decodeURI によって解析された後、フロント エンドはバック エンドから返された中国語のファイル名を取得できます。

ここに画像の説明を挿入

記事のリンクをコピーしてバックエンドに貼り付け、上司に自分で読んでもらいます。

これまでのところ、フロントエンドでできることはたくさんあります。
そこで誰かが、バックエンドのresponse.headersが私が望むContent-Dispositionを返さないのですが、フロントエンドはそれをどのようにキャプチャするのでしょうか、と尋ねたいと考えています。
この点に関して、バックエンドの上司にバックエンド実装のコードを要求してもらい、意味が理解できなかったのでそのまま投稿しました。

Controller端代码(啥是Controller,根本不懂)
 @PostMapping(value="/exportAddresses")
    public Result exportAddresses(HttpServletResponse response){
    
    
        String[] titles = new String[] {
    
    "id","tableCode","columnName"};
        List<Map<String,Object>> objList = new ArrayList<>();
        DownLoadFileController addressService;
        List<NpColumns> npColumnsList = npColumnsService.findByTableCode("APP_TASK_CASE_INFO");
        for(NpColumns item : npColumnsList){
    
    
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("id", item.getId());
            tempMap.put("tableCode", item.getTableCode());
            tempMap.put("columnName", item.getColumnName());
            objList.add(tempMap);
        }
        try {
    
    
            FileUtils.exportExcel(response,"地址树",titles,objList);
            return ResultGenerator.genSuccessResult("导出成功!");
        }catch (Exception e){
    
    
            e.printStackTrace();
            return ResultGenerator.genFailResult("导出失败!");
        }
    }
工具类方法(啥是工具类,也不懂)
public static void exportExcel(HttpServletResponse response,String fileName,String[] titles,List<Map<String,Object>> result){
    
    
        HSSFWorkbook wb;
        OutputStream output = null;
        String tempName = fileName;
        try {
    
    
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            fileName +="_"+df.format(date)+".xls";
            String encodedFilename = URLEncoder.encode(fileName, "UTF-8");
            wb= new HSSFWorkbook();
            HSSFSheet sh = wb.createSheet();
            // 设置列宽
            for(int i = 0; i < titles.length-1; i++){
    
    
                sh.setColumnWidth( i, 256*15+184);
            }
            // 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
            HSSFRow row = sh.createRow(0);
            HSSFCell cell = row.createCell(0);
            cell.setCellValue(new HSSFRichTextString(tempName));
            //cell.setCellStyle(fontStyle(wb));
            sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));
            // 第二行
            HSSFRow row3 = sh.createRow(1);
            // 第二行的列
            for(int i=0; i < titles.length; i++){
    
    
                cell = row3.createCell(i);
                cell.setCellValue(new HSSFRichTextString(titles[i]));
                //cell.setCellStyle(fontStyle(wb));
            }
            //填充数据的内容  i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
            int i = 2, z = 0;
            while (z < result.size()) {
    
    
                row = sh.createRow(i);
                Map<String,Object> map = result.get(z);
                for(int j=0;j < titles.length;j++) {
    
    
                    cell = row.createCell(j);
                    if(map.get(titles[j]) !=null) {
    
    
                        cell.setCellValue(map.get(titles[j]).toString());
                    }else {
    
    
                        cell.setCellValue("");
                    }
                }
                i++;
                z++;
            }
            output = response.getOutputStream();
            response.reset();
            response.addHeader("Content-Type","application/octet-stream;charset=utf-8");
            response.setHeader("Content-disposition", "attachment; filename="+encodedFilename);
            response.setContentType("application/msexcel");
            wb.write(output);
            output.flush();
            output.close();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
最后还有个中文处理乱码那块(这都是啥啥啥,还是不懂)
String encodedFilename = URLEncoder.encode(fileName, "UTF-8");设置文件名的中文编码
response.addHeader("Content-Type","application/octet-stream;charset=utf-8");//这里也设置了相同的编码格式
response.setHeader("Content-disposition", "attachment; filename="+encodedFilename);

より良い実装計画がある場合は、さらに連絡してください

おすすめ

転載: blog.csdn.net/wangjiecsdn/article/details/132339819