当前位置: 首页 > article >正文

Spring Boot 3 文件上传、多文件上传、大文件分片上传、文件流处理以及批量操作

在 Spring Boot 3 中,可以通过内置的文件处理机制结合 Java 的 IO 流与多线程技术,实现文件上传、多文件上传、大文件分片上传、文件流处理以及批量操作的需求。以下是详细实现步骤:

1. 单文件上传

控制器代码

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/file")
public class FileUploadController {

    private final String UPLOAD_DIR = "/path/to/upload/";

    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            File dest = new File(UPLOAD_DIR + file.getOriginalFilename());
            file.transferTo(dest); // 将上传的文件保存到目标位置
            return ResponseEntity.ok("File uploaded successfully: " + file.getOriginalFilename());
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().body("File upload failed");
        }
    }
}

2. 多文件上传

控制器代码

@PostMapping("/upload-multiple")
public ResponseEntity<String> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
    StringBuilder message = new StringBuilder();
    for (MultipartFile file : files) {
        try {
            File dest = new File(UPLOAD_DIR + file.getOriginalFilename());
            file.transferTo(dest);
            message.append("Uploaded: ").append(file.getOriginalFilename()).append("\n");
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().body("Failed to upload some files");
        }
    }
    return ResponseEntity.ok(message.toString());
}

3. 大文件分片上传

分片上传的核心在于将大文件拆分成小块上传,并在服务端进行合并。

分片上传控制器

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

@RestController
@RequestMapping("/file")
public class ChunkUploadController {

    private final String UPLOAD_DIR = "/path/to/upload/";

    @PostMapping("/upload-chunk")
    public ResponseEntity<String> uploadChunk(
            @RequestParam("file") MultipartFile file,
            @RequestParam("chunkNumber") int chunkNumber,
            @RequestParam("totalChunks") int totalChunks,
            @RequestParam("filename") String filename) {

        try {
            File chunkFile = new File(UPLOAD_DIR + filename + ".part" + chunkNumber);
            file.transferTo(chunkFile);

            // 如果所有分片都已上传完毕,则进行合并
            if (isAllChunksUploaded(filename, totalChunks)) {
                mergeChunks(filename, totalChunks);
            }

            return ResponseEntity.ok("Chunk " + chunkNumber + " uploaded successfully");
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().body("Failed to upload chunk");
        }
    }

    private boolean isAllChunksUploaded(String filename, int totalChunks) {
        for (int i = 1; i <= totalChunks; i++) {
            if (!Files.exists(Paths.get(UPLOAD_DIR + filename + ".part" + i))) {
                return false;
            }
        }
        return true;
    }

    private void mergeChunks(String filename, int totalChunks) throws IOException {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(UPLOAD_DIR + filename))) {
            for (int i = 1; i <= totalChunks; i++) {
                File chunkFile = new File(UPLOAD_DIR + filename + ".part" + i);
                Files.copy(chunkFile.toPath(), bos);
                chunkFile.delete(); // 合并后删除分片文件
            }
        }
    }
}

4. 文件流处理

文件流处理对于大文件来说可以减少内存占用,直接使用流式写入。

@PostMapping("/upload-stream")
public ResponseEntity<String> uploadFileStream(@RequestParam("file") MultipartFile file) {
    try (InputStream inputStream = file.getInputStream();
         OutputStream outputStream = new FileOutputStream(UPLOAD_DIR + file.getOriginalFilename())) {

        byte[] buffer = new byte[1024 * 1024]; // 1MB 缓冲区
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }

        return ResponseEntity.ok("File uploaded successfully with streaming");
    } catch (IOException e) {
        e.printStackTrace();
        return ResponseEntity.internalServerError().body("File upload failed");
    }
}

5. 批量文件操作

示例:批量删除文件

@DeleteMapping("/delete-multiple")
public ResponseEntity<String> deleteMultipleFiles(@RequestParam List<String> filenames) {
    StringBuilder message = new StringBuilder();
    for (String filename : filenames) {
        File file = new File(UPLOAD_DIR + filename);
        if (file.exists() && file.delete()) {
            message.append("Deleted: ").append(filename).append("\n");
        } else {
            message.append("Failed to delete: ").append(filename).append("\n");
        }
    }
    return ResponseEntity.ok(message.toString());
}

6. 分片技术的前端配合

前端分片上传示例(React)

function uploadFileInChunks(file) {
    const chunkSize = 2 * 1024 * 1024; // 每片 2MB
    const totalChunks = Math.ceil(file.size / chunkSize);
    let chunkNumber = 0;

    async function uploadChunk() {
        const start = chunkNumber * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);

        const formData = new FormData();
        formData.append("file", chunk);
        formData.append("chunkNumber", chunkNumber + 1);
        formData.append("totalChunks", totalChunks);
        formData.append("filename", file.name);

        await fetch("/file/upload-chunk", {
            method: "POST",
            body: formData,
        });

        chunkNumber++;
        if (chunkNumber < totalChunks) {
            uploadChunk();
        } else {
            console.log("Upload complete");
        }
    }

    uploadChunk();
}

总结

单文件上传:适用于小文件。
多文件上传:批量处理多个文件。
大文件分片上传:解决超大文件的上传需求,并支持断点续传。
文件流处理:高效处理大文件,降低内存占用。
批量操作:如批量删除、下载。
分片技术:结合前端分片,支持更高效的文件上传和管理。
可以根据具体业务需求选择合适的技术方案。


http://www.kler.cn/a/460361.html

相关文章:

  • 41.5 nginx拦截prometheus查询请求使用lua脚本做promql的检查替换
  • 《HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发
  • 第二十六天 自然语言处理(NLP)词嵌入(Word2Vec、GloVe)
  • 【玩转OCR | 基于腾讯云智能结构化OCR的技术应用实践】
  • AWS re:Invent 2024 - Dr. Werner Vogels 主题演讲
  • java中的基本数据类型有哪些?
  • WPF系列五:图形控件Ellipse
  • log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件
  • 自己编写甘特图的绘制程序
  • golang 熔断限流降级
  • 商汤C++开发面试题及参考答案
  • 【postgresql 物化视图】自动刷新物化视图2种方法
  • order by语句执行顺序
  • Vue2/Vue3使用DataV
  • .net core 的数据库编程
  • swiftui开发页面加载发送请求初始化@State变量
  • flash-attention保姆级安装教程
  • 脚本方式 迁移 老GITLAB项目到新GITLAB
  • 前端vue+el-input实现输入框中文字高亮标红效果(学习自掘金博主文章)
  • 服务器系统维护与安全配置
  • 黑马商城:MybatisPlus
  • img上的title属性和alt属性的区别是什么?
  • Oracle 数据库 dmp文件从高版本导入低版本的问题处理
  • C++ 环境搭建 - 安装编译器、IDE选择
  • WebRTC音视频通话系统需求(项目预算)
  • ffmpeg 编译+ libx264