Springboot+vue前后端分离文件上传、下载方式及与Spring的异同(十四)

一、文件上传

1.1 上传方式

系统是上传的Excel文件,与spring的方式是一样的。不再举例(代码详见zbj的ibnr拆分模块)。

可以看下Excel导入的工具类。详见链接:https://www.cnblogs.com/zhangshuaivole/p/13793424.html

1.2 与Spring的异同

1.3 postman 文件下载功能进行测试

后台

@RequestParam("file") MultipartFile[] multipartFile

postman

二、文件下载

2.1 下载方式

1 直接下载(zbj系统也是用的这种方式)

下载工具类:

package com.pdfc.reinsbusiness.utils.excel;

import com.pdfc.reinsbusiness.utils.Campuso2oException;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * @Description: 下载文件的工具类
 * @Author: zs
 * @CreateDate: 2020/9/23 16:29
 */
public class DownloadFileUtil {

    /**
     * 下载文件
     * @param response:相应对象
     */
    public static String downloadFile(String examplePath,HttpServletResponse response, HttpServletRequest request) {

        String msg = null;
        //获取模板文件:注意此处需要配置pom.xml文件;因为spring-boot默认只会读取application.yml配置文件
        ClassPathResource classPathResource = new ClassPathResource(examplePath);
        File file = null;
        try {
            file= classPathResource.getFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String originalFileName = file.getName();
        // 数据校验
        checkParam(originalFileName,file);
        //响应头的处理

        //清空response中的输出流
        response.reset();
        //设置文件大小
        response.setContentLength((int) file.length());
        //设置Content-Type头
        response.setContentType("application/octet-stream;charset=UTF-8");
        //response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        //设置Content-Disposition头 以附件形式解析
        String encodedFilename = getEncodedFilename(request, originalFileName);
        response.addHeader("Content-Disposition", "attachment;filename=" + encodedFilename);

        //将来文件流写入response中
        FileInputStream fileInputStream = null;
        ServletOutputStream outputStream = null;
        try {
            //获取文件输入流
            fileInputStream = new FileInputStream(file);
            //创建数据缓冲区
            byte[] buffers = new byte[1024];
            //通过response中获取ServletOutputStream输出流
            outputStream = response.getOutputStream();
            int length;
            while ((length = fileInputStream.read(buffers)) > 0) {
                //写入到输出流中
                outputStream.write(buffers, 0, length);
            }
            msg = "下载成功";
            return msg;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭
            if(fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return msg;
    }

    /**
     * 下载文件的参数的校验,如果参数不合法则抛出自定义异常
     * @param originalFileName :文件原始文件名
     * @param file :待下载的文件
     */
    private static void checkParam(String originalFileName, File file) {
        if(StringUtils.isBlank(originalFileName)){
            throw new Campuso2oException("输入的文件原始文件名为空");
        }
        if(file == null || !file.exists() ){
            throw new Campuso2oException("待在下载的文件不存在!");
        }
    }

    /**
     * 获取URL编码后的原始文件名
     * @param request :客户端请求
     * @param originalFileName :原始文件名
     * @return*/
    private static String getEncodedFilename(HttpServletRequest request, String originalFileName) {
        String encodedFilename = null;
        String agent = request.getHeader("User-Agent");
        if(agent.contains("MSIE")){
            //IE浏览器
            try {
                encodedFilename = URLEncoder.encode(originalFileName, "utf-8");
                encodedFilename = encodedFilename.replace("+", " ");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }else if(agent.contains("Firefox")){
            //火狐浏览器
            BASE64Encoder base64Encoder = new BASE64Encoder();
            encodedFilename = "=?utf-8?B?" + base64Encoder.encode(originalFileName.getBytes(StandardCharsets.UTF_8))+"?=";
        }else{
            //其他浏览器
            try {
                encodedFilename = URLEncoder.encode(originalFileName, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return encodedFilename;
    }

    /**
     * 获取workbook
     * @return
     */
    public static Workbook getWorkBook(String examplePath){

        //File tempFile = new File("C:\Users\71405469\Desktop\exampleFdeins.xls");
        //获取模板文件:注意此处需要配置pom.xml文件;因为spring-boot默认只会读取application.yml配置文件
        ClassPathResource classPathResource = new ClassPathResource(examplePath);
        File file = null;
        try {
            file= classPathResource.getFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Workbook wookbook = null;
        String fileName = file.getName();
        try {
            InputStream inputStream = new FileInputStream(file);
            wookbook = getWorkBook(inputStream,fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wookbook;
    }

    /**
     * 获取workbook
     * @param inputStream
     * @param fileName
     * @return
     */
    public static Workbook getWorkBook(InputStream inputStream, String fileName){
        Workbook wookbook = null;
        if (fileName.endsWith(".xls")||fileName.endsWith(".xlsx")) {
            try {
                if (fileName.endsWith(".xls")) {
                    wookbook = new HSSFWorkbook(inputStream);//得到excel文件集
                } else if (fileName.endsWith(".xlsx")) {
                    wookbook = new XSSFWorkbook(inputStream);//得到excel文件集
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return wookbook;
    }

    public static ByteArrayOutputStream getOutputStream(Workbook workBook){
        //创建输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            workBook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputStream;
    }
}
View Code

自定义异常:

package com.pdfc.reinsbusiness.utils;

/**
 * @Description: 自定义的校园二手交易平台业务处理过程发生异常
 * @Author: Mark
 * @CreateDate: 2018/10/9 18:06
 * @Version: 2.0
 * @Copyright : 豆浆油条个人非正式工作室
 */
public class Campuso2oException extends RuntimeException{
    public Campuso2oException(String origin){
        super("{"+origin+"}发生了异常:");
    }
    public Campuso2oException(String origin,Exception ex){
        super("{"+origin+"}发生了异常:"+parseErrMsg(ex));

    }

    private static String parseErrMsg(Exception ex) {
        if(ex == null){
            return "异常堆栈获为空";
        }
        String errMsg = "";
        StackTraceElement[] stackTrace = ex.getStackTrace();
        for (StackTraceElement s : stackTrace) {
            errMsg+="	at " + s + "
";
        }
        return errMsg;
    }
}
View Code

2、返回数据流,前台通过link方式处理Byte字节流

【1】后台,zt代码:

生成Excel文件:

@Override
    public ByteArrayOutputStream exportFdreinsList(FdreinsVo fdreinsVo,List<FdreinsVo> fdreinsVoLists,Boolean isFromPage) {

        String sheetName = "";
        //excel文件名
        String fileName = "再保险人信息维护导出" + System.currentTimeMillis() + ".xlsx";
        //获取表头名称
        String[] headers = ExcelUtils.getHeaders(FdreinsVo.class);
        //获取字段属性
        String[] fields = ExcelUtils.getFields(FdreinsVo.class);
        //获取数据集
        List<FdreinsVo> fdreinsVoList = new ArrayList<>();
        if(isFromPage){
            fdreinsVoList = fdreinsVoLists;
        }else {
            fdreinsVoList = getFdreinsList(fdreinsVo);
        }
        //创建初始工作簿
        //SXSSFWorkbook sxssfWorkbook = ExportUtil.createWorkbook(1000);
        XSSFWorkbook wb = new XSSFWorkbook();
        //设置Excel格式
        XSSFCellStyle titleCellStyle = getTitleCellStyle(wb);
        XSSFCellStyle textCellStyle = getTextCellStyle(wb);
        ByteArrayOutputStream outputStream = null;
        try {
            //生成Excel文件
            ExportUtils.exportByStyle(fileName, sheetName, fdreinsVoList, headers, fields, wb, titleCellStyle, textCellStyle);
            //ExportUtils.exportExcel(sheetName,headers,fields,0,sxssfWorkbook,fdreinsVoList);
            //导出Excel文件
            //ExcelUtils.outputToFile(fileName,wb);
            //生成数据流
            outputStream = ExportUtils.responseWorkbook(sheetName,wb);
            return outputStream;
        } catch (Exception e) {
            LOG.info("在生成Excel时出现错误:"+e);
            return  null;
        }
    }

将Excel文件转成数据流

/**
     * 将Excel转成数据流
     * responseWorkbook
     * @param title  title
     * @param wb wb
     * @throws IOException IOException
     */
    public static ByteArrayOutputStream responseWorkbook(String title, Workbook wb)throws IOException{
        ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
        wb.write(outByteStream);
        return  outByteStream;
    }

并参看excel导出工具类:详情链接:https://www.cnblogs.com/zhangshuaivole/p/13793392.html

【2】前台:

springboot返回文件流,前端使用vue->a->link生成txt文件或sql文件

参看链接:

https://blog.csdn.net/m0_37930141/article/details/108470828

https://blog.csdn.net/ycd500756/article/details/87907525

2.2 与Spring的异同

需要注意的是,Spring-boot用的是前后端分离的方式进行开发的,后台返回到前台的均为byte字节流。

2.3postman 文件下载功能进行测试

原文地址:https://www.cnblogs.com/zhangshuaivole/p/13787265.html