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);
      });
    };
相关推荐
Mintopia2 分钟前
🧠 AIGC模型的增量训练技术:Web应用如何低成本迭代能力?
前端·javascript·aigc
Mintopia3 分钟前
🧩 Next.js在国内环境的登录机制设计:科学、务实、又带点“国风味”的安全艺术
前端·javascript·全栈
paopaokaka_luck5 分钟前
基于SpringBoot+Vue的少儿编程培训机构管理系(WebSocket及时通讯、协同过滤算法、Echarts图形化分析)
java·vue.js·spring boot·后端·spring
qq. 280403398415 分钟前
react hooks
前端·javascript·react.js
用户40993225021222 分钟前
PostgreSQL 查询慢?是不是忘了优化 GROUP BY、ORDER BY 和窗口函数?
后端·ai编程·trae
半夏知半秋24 分钟前
skynet.newservice接口分析
笔记·后端·学习·安全架构
陈小桔39 分钟前
Springboot之常用注解
java·spring boot·后端
LHX sir1 小时前
什么是UIOTOS?
前端·前端框架·编辑器·团队开发·个人开发·web
Gazer_S1 小时前
【前端状态管理技术解析:Redux 与 Vue 生态对比】
前端·javascript·vue.js
数据知道1 小时前
Go基础:一文掌握Go语言泛型的使用
开发语言·后端·golang·go语言