# SpringBoot集成文件

# 基础的文件上传与下载

# 引入依赖

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

# yml配置

spring:
  servlet:
    multipart:
      max-file-size: 10MB # 单个文件大小
      max-request-size: 500MB # 总文件大小

# 使用

文件长传

    @PostMapping("/upload")
    public ResponseResult<String> upload(@RequestParam(value="file",required = true) MultipartFile file){
        try {
            String uploadPath = "d:/upload";
            File uploadDir = new File(uploadPath);
            if(!uploadDir.exists()){
                uploadDir.mkdir();
            }
            log.info(uploadDir.getAbsolutePath());
            // new一个本地文件
            File localFile = new File(uploadPath + File.separator + file.getOriginalFilename());
            // 保存到本地
            file.transferTo(localFile);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.fail(e.getMessage());
        }
        return ResponseResult.success();
    }

文件下载

    @GetMapping("/download")
    public void download(HttpServletResponse response){
        response.reset(); // 清除任何已设置的内容和头部信息
        response.setContentType("application/octet-stream");// 通用的二进制流
        // Content-disposition 指示如何处理接收到的响应内容
        // 接受的内容为一个附件,触发浏览器下载,指定文件名
        response.setHeader("Content-disposition",
                "attachment;filename=file_"+System.currentTimeMillis()+".pdf");
        File file = new File("d:download/毛泽东选集.pdf");
        // 建立输入流
        try (FileInputStream inputStream = new FileInputStream(file)){
            byte[] b = new byte[1024]; // 临时存储输入流中的数据
            int len;
            while((len = inputStream.read(b))>0){
                response.getOutputStream().write(b,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

原文链接 https://www.pdai.tech/md/spring/springboot/springboot-x-file-upload-download.html

# 大文件上传(补充)

# 基于分片的断点续传和秒传

  • 分片上传:大文件分成若干份大小相等的小文件,等所有小文件上传成功后再合并成完整的原始文件
  • 断点续传:重新上传文件时先判断那些文件已经上传过了,如果上传过了跳过这些块,否则则上传
  • 秒传:检测是否已经上传过了

前后端分工?

  • 前端:file.slice()分成多个文件,并计算md5值
  • 后端,许接受每次上传的文件块并保存文件块信息,所有文件块上传完毕,合并为大文件

异步上传:

@EnableAsync 用在Springboot启动类上

@Async 用在方法上

# Excel文件上传下载

# 集成POI

# 引入依赖

  1. poi支持xls、poi-ooxml支持xlsx文件
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.2</version>
        </dependency>

# 使用

  1. controller
@ApiOperation("下载Excel")
@GetMapping("/excel/download")
public void download(HttpServletResponse response){
    try {
        SXSSFWorkbook workbook = userService.generateExcelWorkbook();
        response.reset();
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-disposition","attachment;filename=user_excel_" + 					System.currentTimeMillis() + ".xlsx");
        ServletOutputStream os = response.getOutputStream();
        workbook.write(os);
        workbook.dispose();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  1. service
/**
     * 生成工作文件
     * @return
     */
@Override
public SXSSFWorkbook generateExcelWorkbook() {
    SXSSFWorkbook workbook = new SXSSFWorkbook();
    Sheet sheet = workbook.createSheet();
    int rows = POSITION_ROW;
    int cols = POSITION_COL;

    // 表头
    Row head = sheet.createRow(rows++);
    String[] cloumns = new String[]{"ID", "Name", "Email", "Phone", "Description"};
    int[] colWidths = new int[]{2000, 3000, 5000, 5000, 8000};
    CellStyle headStyle = getHeadCellStyle(workbook);
    for(int i=0;i<cloumns.length;i++){
        sheet.setColumnWidth(cols,colWidths[i]);
        addCellWithStyle(head, cols++, headStyle).setCellValue(cloumns[i]);
    }

    // 表内容
    CellStyle bodyStyle = getBodyCellStyle(workbook);
    for(User user : getUserList()){
        cols = POSITION_COL;
        Row row = sheet.createRow(rows++);
        addCellWithStyle(row,cols++,bodyStyle).setCellValue(user.getId());
        addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getUserName());
        addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getEmail());
        addCellWithStyle(row, cols++, bodyStyle).setCellValue(String.valueOf(user.getPhoneNumber()));
        addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getDescription());
    }
    return workbook;
}

# 集成EasyExcel

阿里开源的基于POI封装的EXCEL处理库,使用了缓冲区,降低读取excel文件时使用的内存

# 引入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>

# 读excel

读取excel代码

@Test
public void testRead(){
    File file = new File("e:\\查询船舶.csv");
    EasyExcel.read(file, Ship.class, new ShipReadListener())
        .sheet()
        .doRead();
}

实体类Ship


@Getter
@Setter
@EqualsAndHashCode
public class Ship {
    @ColumnWidth(15) // 列宽
    @ExcelProperty("fLong") // 列名
    private double lon;

    @ColumnWidth(15)
    @ExcelProperty("fLat")
    private double lat;

    @ColumnWidth(20)
    @DateTimeFormat("yyyy/MM/dd HH:mm")
    @ExcelProperty(index = 2)
    private String date;

    @Override
    public String toString() {
        return "Ship{" +
            "lon=" + lon +
            ", lat=" + lat +
            ", date='" + date + '\'' +
            '}';
    }
}

自定义读监听器


/**
 * 自定义读监听器,需要实现ReadListener接口
 */
public class ShipReadListener implements ReadListener<Ship> {
    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    public static final int BATCH_COUNT = 5;

    /**
     * 缓存的数据
     */
    private List<Ship> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * 每一条数据解析都会调用
     * @param ship  excel数据对象
     * @param analysisContext
     */
    @Override
    public void invoke(Ship ship, AnalysisContext analysisContext) {
        //System.out.println(ship.toString());
        cachedDataList.add(ship);
        if(cachedDataList.size() >= BATCH_COUNT){
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            System.out.println("清空缓存");
        }
    }

    /**
     * 全部解析完成,把剩下的存入数据库
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("存储数据库成功");
    }
}

# 写excel

@Test
public void testWrite(){
    File file = new File("e:\\船舶模拟数据.xlsx");
    // 忽略某些列
    HashSet<String> excludeColumns = new HashSet<String>();
    //excludeColumns.add("lon");
    EasyExcel.write(file, Ship.class)
        .excludeColumnFieldNames(excludeColumns)
        .sheet("船舶模拟数据")
        .doWrite(getData());
}

mock数据

// 生成数据
private List<Ship> getData(){
    List<Ship> list = ListUtils.newArrayList();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
    for (int i = 0; i < 100; i++) {
        Ship ship = new Ship();
        ship.setLon(117.894562 + Math.random());
        ship.setLat(36.985712 + Math.random());
        ship.setDate(LocalDateTime.now().format(formatter));
        list.add(ship);
    }
    return list;
}

# web写

在web中写入也很简单,只需要定义实体类,标注类名,字段格式

@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
    // 指定响应内容为xlsx格式
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    // 防止中文乱码
    String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
    // 告诉浏览器这是一个应该立即下载的文件,并且指定文件名
    response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").doWrite(data());
}

private List<User> data() {
    List<User> list = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        User user = new User();
        user.setName("theonefx" + i);
        user.setAge(i);
        list.add(user);
    }
    return list;
}

访问http://localhost:8080/download

# Word导出

# itextpdf导出PDF

Last Updated: 12/23/2024, 4:18:13 AM