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