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);
      });
    };
相关推荐
程序员爱钓鱼35 分钟前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__40 分钟前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
阿珊和她的猫3 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
uzong6 小时前
技术故障复盘模版
后端
GetcharZp7 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
加班是不可能的,除非双倍日工资7 小时前
css预编译器实现星空背景图
前端·css·vue3
桦说编程7 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip8 小时前
vite和webpack打包结构控制
前端·javascript