前言

在开发中会遇到导入文件后,失败的数据需要整理在加上导入失败原因。

按照目前主流的方法,要么通过流输出到response响应体中,或者把失败的excel上传到服务器中,返回url让前端下载。


一、需求

导入文件后,把未满足条件的记录和未满足的原因导出,让业务人员修改后二次导入。

二、需求分析

1、当前端请求到后端时,可以直接通过response直接导出文件,但是会有其他情况,前端需要返回码去判断展示不同的页面。

2、故放弃第1种方法,需要让 excel 暂存在一个地方 , 通过返回的数据, 由前端判断去获取excel。

3、有多种实现方法。 本文主要介绍的是在 session中存储。

三、代码

<dependency>
 	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
   <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
package com.example.springboot_demo.testImpl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

@RestController
@Slf4j
public class TestController {

    @GetMapping("/import")
    public String test2(@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request){
        // TODO 处理file

        // 构造错误数据
        List<TempFileUtil.ErrorExportVO> errorExportVOList = new ArrayList<>();
        TempFileUtil.ErrorExportVO exportVO1 = new TempFileUtil.ErrorExportVO();
        exportVO1.setFileName("我是错误的文件名!");
        exportVO1.setErrorMsg("文件名错误!");
        TempFileUtil.ErrorExportVO exportVO2 = new TempFileUtil.ErrorExportVO();
        exportVO2.setFileName("我是错误的文件名2!");
        exportVO2.setErrorMsg("文件名错误2!");
        errorExportVOList.add(exportVO1);
        errorExportVOList.add(exportVO2);

        String uuid;
        try{
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ExcelWriterBuilder write = EasyExcel.write(outputStream, TempFileUtil.ErrorExportVO.class);
            write.sheet("sheet1").doWrite(errorExportVOList);
            uuid = TempFileUtil.addExcel(request, outputStream, "错误信息");
            outputStream.close();
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
        return uuid;
    }


    //下载临时文件
    @GetMapping("/downloadTempFile")
    public void downloadTempFile(@RequestParam("tempFileId") String tempFileId,
                                 HttpServletRequest request, HttpServletResponse response) {
        final TempFileUtil.TempFileBean fileBean = TempFileUtil.get(request, tempFileId);
        if (fileBean == null) {
            throw new RuntimeException("对象不存在!");
        }
        TempFileUtil.exportBinary(fileBean, response);
        TempFileUtil.remove(request, tempFileId);
    }
}

package com.example.springboot_demo.testImpl;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class TempFileUtil {
    @SuppressWarnings("unchecked")
    private static Map<String, TempFileBean> getFileMap(HttpServletRequest request) {
        if (request == null) {
            return new HashMap<>();
        }
        final HttpSession session = request.getSession();
        if (session.getAttribute("fileMap") == null) {
            session.setAttribute("fileMap", new HashMap<String, TempFileBean>());
        }
        return (Map<String, TempFileBean>) session.getAttribute("fileMap");
    }

    public static void put(HttpServletRequest request, final TempFileBean fileBean) {
        getFileMap(request).put(fileBean.getFileId(), fileBean);
    }

    public static TempFileBean get(HttpServletRequest request, final String fileId) {
        return getFileMap(request).get(fileId);
    }

    public static void remove(HttpServletRequest request, final String fileId) {
        getFileMap(request).remove(fileId);
    }

    public static String addExcel(HttpServletRequest request, ByteArrayOutputStream outputStream, String fileName) {
        byte[] excelData = outputStream.toByteArray();
        TempFileBean fileBean = new TempFileBean();
        String fileId = UUID.randomUUID().toString();
        fileBean.setFileId(fileId);
        fileBean.setFileName(fileName);
        fileBean.setFileContent(excelData);
        TempFileUtil.put(request, fileBean);
        return fileId;

    }

    public static void exportBinary(TempFileBean fileBean, HttpServletResponse response) {
        try {
            // 对中文文件名进行 URL 编码
            String encodedFileName = URLEncoder.encode(fileBean.getFileName(), "utf-8") + ExcelTypeEnum.XLSX.getValue();
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);

            try (OutputStream os = response.getOutputStream()) {
                os.write(fileBean.getFileContent());
                os.flush();
            } catch (Exception e) {
                log.info("系统异常");
            }
        } catch (Exception e) {
            log.info("系统异常");
        }


    }

    @Data
    public static class TempFileBean {
        private String fileId;
        private String fileName;
        private byte[] fileContent;
    }

    @Data
    public static class ErrorExportVO {
        @ExcelProperty(value = "文件名")
        @ColumnWidth(30)
        private String fileName;
        @ExcelProperty(value = "错误原因")
        @ColumnWidth(30)
        private String errorMsg;
    }
}

【贫民版】Springboot导入返回错误Excel表格 ---- 通过session存储字节数据,再获取写到响应体中。-LMLPHP

03-29 06:08