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

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

1. 单文件上传

控制器代码

java 复制代码
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. 多文件上传

控制器代码

java 复制代码
@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. 大文件分片上传

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

分片上传控制器

java 复制代码
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. 文件流处理

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

java 复制代码
@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. 批量文件操作

示例:批量删除文件

java 复制代码
@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)

js 复制代码
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();
}

总结

单文件上传:适用于小文件。

多文件上传:批量处理多个文件。

大文件分片上传:解决超大文件的上传需求,并支持断点续传。

文件流处理:高效处理大文件,降低内存占用。

批量操作:如批量删除、下载。

分片技术:结合前端分片,支持更高效的文件上传和管理。

可以根据具体业务需求选择合适的技术方案。

相关推荐
不倒翁玩偶2 小时前
IDEA导入新的SpringBoot项目没有启动按钮
java·spring boot·intellij-idea
小小小米粒2 小时前
Maven Tools
java
苏三说技术2 小时前
xxl-job 和 elastic-job,哪个更好?
后端
三小河2 小时前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端
kali-Myon2 小时前
2025春秋杯网络安全联赛冬季赛-day1
java·sql·安全·web安全·ai·php·web
我是咸鱼不闲呀2 小时前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
三小河2 小时前
前端视角详解 Agent Skill
前端·javascript·后端
清水白石0083 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
牛奔3 小时前
Go 是如何做抢占式调度的?
开发语言·后端·golang
颜酱3 小时前
二叉树遍历思维实战
javascript·后端·算法