SpringBoot之结合前端Axios及其他多种方式下载文件

SpringBoot之结合前端Axios及其他多种方式下载文件

文章目录

  • SpringBoot之结合前端Axios及其他多种方式下载文件
  • [1. 后端](#1. 后端)
    • [1. 文件下载工具类](#1. 文件下载工具类)
    • [2. 文件下载controller](#2. 文件下载controller)
  • [2. 前端多种方式下载](#2. 前端多种方式下载)
    • [1. 下载方式1(a标签)](#1. 下载方式1(a标签))
    • [2. 下载方式2(window.location.href)](#2. 下载方式2(window.location.href))
    • [3. 下载方式3(axios)](#3. 下载方式3(axios))
    • [4. 使用fileDownload插件](#4. 使用fileDownload插件)

1. 后端

以spring boot工程为例进行文件下载

1. 文件下载工具类

java 复制代码
package com.yuan.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @Description: 文件操作工具类
 * @Author: 袁金生
 * @CreateTime: 2022-11-15 14:56
 * @LastEditors: 袁金生
 * @LastEditTime: 2022-11-15 14:56
 */
@Slf4j
public class FileUtil {
    /**
     * 文件下载
     *
     * @param response 响应对象
     * @param fileName 文件全名
     * @param filePath 文件路径(路径+文件名)
     */
    public final static void fileDownload(HttpServletResponse response, String fileName, String filePath) {
        OutputStream outputStream = null;
        try {
            File saveFile = new File(filePath);
            if (saveFile.exists()) {
                //设置返回类型
                response.setContentType("application/octet-stream");
                //对文件名称进行编码,解决文件名称中中文乱码问题
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                //获取文件输入流字节数组,这里使用的是org.apache.commons.io.FileUtil工具类
                byte[] byteArray = FileUtils.readFileToByteArray(saveFile);
                //输入流转输出流返回给客户端
                outputStream = new BufferedOutputStream(response.getOutputStream());
                if (byteArray != null && byteArray.length > 0) {
                    outputStream.write(byteArray);
                }
            } else {
                //设置头信息
                response.setContentType("text/html;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.write("[" + fileName + "]文件不存在!");
                log.warn("[{}]文件不存在!", fileName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        log.info("下载完成:{}", fileName);
    }
}

2. 文件下载controller

java 复制代码
package com.yuan.wechat.controller;

import com.yuan.utils.ApiResult;
import com.yuan.utils.FileUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * 通用跳转前端控制器
 * </p>
 *
 * @author 袁金生
 * @since 2022-11-02
 */
@RestController
@RequestMapping("/wechat")
public class CommonController {

    /**
     * 通用跳转
     *
     * @param pageName
     * @return
     */
    @RequestMapping("/toPage")
    public ModelAndView toPage(@RequestParam String pageName) {
        return new ModelAndView(pageName);
    }

    @GetMapping("/downloadReport")
    public Object downloadReport(@RequestParam("reportName") String reportName, @RequestParam("reportPath") String reportPath, HttpServletResponse response) {
        if (StringUtils.isBlank(reportName) || StringUtils.isBlank(reportPath)) {
            return ApiResult.error("报告名或报告路径不能为空");
        }
        String diskFilePath = reportPath + reportName;
        FileUtil.fileDownload(response, reportName, diskFilePath);
        return null;
    }
}

2. 前端多种方式下载

前端是基于springboot单体下结合vue+axios进行下载

1. 下载方式1(a标签)

js 复制代码
const downloadReport = (reportName, reportPath) => {
        console.log("下载报告reportName===1》", reportName)
        console.log("下载报告reportPath===1》", reportPath)
        reportName = "Java开发手册(黄山版).pdf";
        reportPath = "D:/aa/files/"
       /* const url = ctxPath + '/wechat/downloadReport?reportName='+reportName+'&reportPath='+reportPath
        let link = document.createElement('a');
        link.href = url
        //link.download = item.fileName || '下载文件';//下载后文件名
        document.body.appendChild(link);
        link.click();//点击下载
        link.remove();//下载完成移除元素
        window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;*/
        // 上述请求也可以按以下方式完成(可选)
        axios.get(ctxPath + '/wechat/downloadReport', {
            params: {
                reportName,
                reportPath
            },
            responseType: 'blob',//响应类型为流
            onDownloadProgress: (ProgressEvent) => {//用来计算下载量(实际项目中可以用来显示下载进度)
                let total = item.fileLength;
                console.log(total);
                let load = ProgressEvent.loaded;
                console.log(load);
            }
        }).then(function (resp) {
            console.log("resp",resp);
            if (resp) {
                let blob = new Blob([resp]);//处理文档流
                let url = window.URL.createObjectURL(blob);
                let link = document.createElement('a');
                link.href = url
                link.download = reportName || '下载文件';//下载后文件名
                document.body.appendChild(link);
                link.click();//点击下载
                link.remove();//下载完成移除元素
                window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;
            } else {
                console.error('文件下载失败,请重试!');
            }
        }).catch(function (error) {
            console.log(error);
        }).finally(() => {
            //请求结束回调
        })
        // http://localhost:7001/lims/wechat/toPage?pageName=wechat/tabbar
        //window.location.href = ctxPath + "wechat/toPage?pageName=wechat/pdfView";
    };

2. 下载方式2(window.location.href)

shell 复制代码
const downloadReport = (reportName, reportPath) => {
        console.log("下载报告reportName===1》", reportName)
        console.log("下载报告reportPath===1》", reportPath)
        reportName = "Java开发手册(黄山版).pdf";
        reportPath = "D:/aa/files/"
        window.location.href = ctxPath + '/wechat/downloadReport?reportName='+reportName+'&reportPath='+reportPath
    };

3. 下载方式3(axios)

  1. 案例1,文件名从响应对象中获取
javascript 复制代码
const downloadReport = () => {
        axios(ctxPath + '/generator/genCloudCode', {
            method: 'post', // 默认值get
            data: {...cloudForm},
            //更多配置查看官网 https://www.axios-http.cn/docs/req_config
            responseType: 'blob',//表示浏览器将要响应的数据类型(默认json),选项包括 'arraybuffer', 'document', 'json', 'text', 'stream';浏览器专属:'blob'
            headers: {'Content-Type': 'application/json; application/octet-stream'},
            onDownloadProgress: (ProgressEvent) => {//用来计算下载量(实际项目中可以用来显示下载进度)
                let load = ProgressEvent.loaded;
                console.log(load);
            }
        }).then(function (resp) {
            console.log("resp", resp);
            //响应回来后其实还是使用的a标签进行下载的
            if (resp) {
                //从响应对象中获取头信息,content-disposition包含了服务端返回的文件名
                let header = resp.headers['content-disposition'];
                const fileName = decodeURI(header.substring(header.indexOf("=") + 1));
                console.log("header",header)
                console.log("fileName",fileName)

                let blob = new Blob([resp.data], {type: resp.headers['content-type']});//type指定响应的ContentType,这里从响应头中获取
                let url = window.URL.createObjectURL(blob);
                let link = document.createElement('a');
                link.href = url
                link.download = fileName || '下载文件';//下载后文件名
                document.body.appendChild(link);
                link.click();//点击下载
                link.remove();//下载完成移除元素
                window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;
            } else {
                console.error('文件下载失败,请重试!');
            }
        }).catch(function (error) {
            console.log(error);
        }).finally(() => {
            //请求结束回调
        })
    };
  1. 案例2,文件名自定义
js 复制代码
const downloadReport = (reportName, reportPath) => {
        console.log("下载报告reportName===1》", reportName)
        console.log("下载报告reportPath===1》", reportPath)
        reportName = "Java开发手册(黄山版).pdf";
        reportPath = "D:/aa/files/"
        axios.get(ctxPath + '/wechat/downloadReport', {
            params: {
                reportName,
                reportPath
            },
            responseType: 'blob',//响应类型为流,这里可以指定为blob或arraybuffer
            onDownloadProgress: (ProgressEvent) => {//用来计算下载量(实际项目中可以用来显示下载进度)
                let load = ProgressEvent.loaded;
                console.log(load);
            }
        }).then(function (resp) {
            console.log("resp",resp);
            //响应回来后其实还是使用的a标签进行下载的
            if (resp) {
                let blob = new Blob([resp.data]);
                let url = window.URL.createObjectURL(blob);
                let link = document.createElement('a');
                link.href = url
                link.download = reportName || '下载文件';//下载后文件名
                document.body.appendChild(link);
                link.click();//点击下载
                link.remove();//下载完成移除元素
                window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;
            } else {
                console.error('文件下载失败,请重试!');
            }
        }).catch(function (error) {
            console.log(error);
        }).finally(() => {
            //请求结束回调
        })
    };

4. 使用fileDownload插件

fileDownload插件git地址:FileDownload

js 复制代码
const downloadReport = (reportName, reportPath) => {
      console.log("下载报告reportName===1》", reportName)
      console.log("下载报告reportPath===1》", reportPath)
      reportName = "Java开发手册(黄山版).pdf";
      reportPath = "D:/aa/files/"
      axios.get(ctxPath + '/wechat/downloadReport', {
            params: {
                reportName,
                reportPath
            },
        responseType: 'blob',
      }).then(res => {
        fileDownload(res.data, reportName);
      });
    };
相关推荐
高兴达30 分钟前
Spring boot入门工程
java·spring boot·后端
伍哥的传说44 分钟前
鸿蒙系统(HarmonyOS)应用开发之手势锁屏密码锁(PatternLock)
前端·华为·前端框架·harmonyos·鸿蒙
yugi9878381 小时前
前端跨域问题解决Access to XMLHttpRequest at xxx from has been blocked by CORS policy
前端
幽络源小助理1 小时前
SpringBoot基于JavaWeb的城乡居民基本医疗信息管理系统
java·spring boot·学习
浪裡遊1 小时前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
旧曲重听12 小时前
最快实现的前端灰度方案
前端·程序人生·状态模式
默默coding的程序猿2 小时前
3.前端和后端参数不一致,后端接不到数据的解决方案
java·前端·spring·ssm·springboot·idea·springcloud
夏梦春蝉2 小时前
ES6从入门到精通:常用知识点
前端·javascript·es6
归于尽2 小时前
useEffect玩转React Hooks生命周期
前端·react.js
G等你下课2 小时前
React useEffect 详解与运用
前端·react.js