前后端封装上传下载

前后端封装上传下载

前端:

js 复制代码
export const download = (url, data = {}, method = 'get') => {
    return request({
        url,
        method,
        //上传下载只用 GET 和 POST,不会用 PUT/DELETE。
       [method === 'get' ? 'params' : 'data']: data,
        responseType: 'blob'
    }).then((response) => { // 【修改点】这里接收到的是完整的 response 对象

        const blob = response.data // 从 response 中取出 blob

        const link = document.createElement('a')
        const blobUrl = URL.createObjectURL(blob)
        link.href = blobUrl

        // 【修改点】从 response.headers 中获取文件名
        const contentDisposition = response.headers?.['content-disposition']
        let filename = 'file' // 默认文件名
        if (contentDisposition) {
            const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
            if (match && match[1]) {
                filename = decodeURIComponent(match[1].replace(/['"]/g, '')) // 顺便解码防止中文乱码
            }
        }

        link.download = filename
        document.body.appendChild(link) // 兼容 Firefox
        link.click()
        document.body.removeChild(link) // 清理 DOM
        URL.revokeObjectURL(blobUrl) // 释放内存
    })
}
// 不用get,get长度有限,put虽然也是放在请求体的数据,但put都是修改为主,delete是删除所以用post
export function uploadFile(url, file, extraData ={}){
  const formData = new FormData();
  formData.append('file', file);

  // 用于放置额外参数,追加到 formData 中
  Object.keys(extraData).forEach(key => {
    formData.append(key, extraData[key])
  })

  return request({
    url,
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

后端:

java 复制代码
package com.demo.common;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @Description:
 * @Author:sfk
 * @Data:2026/7/2
 **/
public class FileUtils {

    public static void downloadPdf(HttpServletResponse response, String fileName, byte[] outPutContent) throws IOException {
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename="+ fileName+".pdf");
        response.getOutputStream().write(outPutContent);
        response.getOutputStream().flush();
    }

    // T 可以接收任意Java类型
    public static <T> void downloadExcel(HttpServletResponse response,String fileName, Class<T> clazz, List<T> dataList) throws IOException {
        setExcelResponseHeader(response, fileName);
        // 内容样式:居中 + 字体大小16
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 16);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 表头样式:不设置任何样式,保持默认
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();

        // 创建策略
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        // 输出文件
        EasyExcel.write(response.getOutputStream(), clazz)
                .registerWriteHandler(horizontalCellStyleStrategy)
                .sheet(fileName)
                .doWrite(dataList);
    }

    public static <T> void exportExcel(HttpServletResponse response,String fileName,Class<T> clazz,List<T> datalist) throws IOException {
        setExcelResponseHeader(response, fileName);

        EasyExcel.write(response.getOutputStream(), clazz)
                .sheet(fileName)
                .doWrite(datalist);
    }

    public static void setExcelResponseHeader(HttpServletResponse response,String fileName){
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // + 时间戳区别区别重复下载
        String name = URLEncoder.encode(fileName + "_" +LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx", StandardCharsets.UTF_8);
        // 去空格 + 指定编码
        String encodedName = URLEncoder.encode(name, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment; filename=" + encodedName);
    }
}

controller调用处:

java 复制代码
@Operation(summary = "导出PDF成绩单")
    @GetMapping("/downloadGradePdf")
    public void downloadGradeById(@RequestParam Long gradeId, HttpServletResponse response) throws IOException {
        try {
            byte[] pdfBytes = gradeService.generateGradePdf(gradeId);
            FileUtils.downloadPdf(response,"成绩单_"+gradeId,pdfBytes);
        } catch(Exception e) {
        	e.printStackTrace();
        }
    }
JAVA 复制代码
@Operation(summary = "导出Excel成绩单")
    @PostMapping("/downloadGradeExcel")
    public void downloadGradeExcel(HttpServletResponse response,@RequestBody GradeQueryReq queryDTO) throws IOException {
        // 调用业务
        List<GradeExportVO> gradeExportVOS = gradeService.generateGradeExcel(queryDTO);

        if (gradeExportVOS == null){
            throw new BusinessException("没有数据!");
        }
        String fileName = "成绩单";
        FileUtils.downloadExcel(response,fileName,GradeExportVO.class,gradeExportVOS);
    }
java 复制代码
@GetMapping("/downloadTemplate")
public void downloadTemplate(HttpServletResponse response) throws IOException {
	    List<UserImportDto> dataList = new ArrayList<>();
        // 示例数据
        UserImportDto example1 = new UserImportDto();
        example1.setUserName("zhangsan");
        example1.setRealName("张三");
        example1.setRole("学生");
        example1.setClassName("计算机科学与技术1班");
        dataList.add(example1);
    
       FileUtils.exportExcel(response,"userImportTemplate",UserImportDto.class,dataList);
}