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();
}

总结

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

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

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

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

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

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

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

相关推荐
Joy T2 小时前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
m0_587383005 小时前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
·云扬·6 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
代码不停7 小时前
自动化测试(java)
java·开发语言·selenium·自动化
行百里er7 小时前
Redis 完结篇——Redis 热点问题在 Spring Boot 项目中实战
redis·后端
高频因子挖掘机8 小时前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
鬼手点金8 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
孟健9 小时前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
paopaokaka_luck9 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
SL_staff10 小时前
JVS混合架构实践:能力引擎+动态模型如何支撑企业级可持续交付
spring boot·低代码·全栈