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

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

文章目录

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

1. 后端

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

1. 文件下载工具类

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

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;

/**
 * 

* 通用跳转前端控制器 *

* * @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标签)

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)

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,文件名从响应对象中获取
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,文件名自定义
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

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);
      });
    };

你可能感兴趣的:(Springboot,Axios,vue,spring,boot,前端,后端,vue,axios)