private String UPLOAD_URL = "F:/20230509/";
private String UPLOAD_SUFFIX_URL = "/gsl/www/";
public String getUPLOAD_URL() {
return UPLOAD_URL + UPLOAD_SUFFIX_URL;
}
@PostMapping("/o_upload")
public Result upload1(@RequestParam("file") MultipartFile multipartFile,
@RequestParam("fileName") String fileName,
@RequestParam("chunkNumber") int chunkNumber,
@RequestParam("totalChunks") int totalChunks) throws IOException {
UserDetail user = SecurityUser.getUser();
String originalFileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
String fileExtension = getFileExtension(originalFileName);
String uniqueFileName = fileName + "_" + chunkNumber + "." + fileExtension;
Path uploadPath = Paths.get(this.getUPLOAD_URL());
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}
Path filePath = Paths.get(this.getUPLOAD_URL() + uniqueFileName);
Files.write(filePath, multipartFile.getBytes());
if (chunkNumber == totalChunks - 1) {
return mergeChunks(fileName, totalChunks, fileExtension, user.getId());
} else {
return new Result().error("上传失败");
}
}
private String getFileExtension(String fileName) {
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex > 0) {
return fileName.substring(dotIndex + 1);
} else {
return "";
}
}
/**
* 合并分片
* @param fileName
* @param totalChunks
* @param fileExtension
* @param userId
* @return
* @throws IOException
*/
private Result mergeChunks(String fileName, int totalChunks, String fileExtension, Long userId) throws IOException {
Path mergedFilePath = Paths.get(this.getUPLOAD_URL() + fileName + "." + fileExtension);
if (!Files.exists(mergedFilePath)) {
Files.createFile(mergedFilePath);
}
for (int i = 0; i < totalChunks; i++) {
Path chunkFilePath = Paths.get(this.getUPLOAD_URL() + fileName + "_" + i + "." + fileExtension);
Files.write(mergedFilePath, Files.readAllBytes(chunkFilePath), StandardOpenOption.APPEND);
Files.delete(chunkFilePath);
}
Path filePath = Paths.get(this.getUPLOAD_URL() + fileName);
File file = new File(filePath.toString());
// 原文件名称
String extension = file.getName().substring(0, file.getName().lastIndexOf("."));
// 后缀
String suffix = "." + file.getName().substring(file.getName().lastIndexOf(".") + 1);
// 新的文件名称
String newFileName = System.currentTimeMillis() + suffix;
// 文件重命名
File renamedFile = new File(file.getParent(), newFileName);
file.renameTo(renamedFile);
// 文件路径:/gsl/cms/1683616117391.zip
String resourceUrl = UPLOAD_SUFFIX_URL + newFileName;
// 可保存到数据库
Map<String, Object> map = new HashMap<>();
map.put("url", resourceUrl);
return new Result().ok(map);
}
注意:合并分片代码中:
Files.write(mergedFilePath, Files.readAllBytes(chunkFilePath), StandardOpenOption.APPEND);
StandardOpenOption.APPEND
,无法打开合并后的文件DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File Upload Testtitle>
head>
<body>
<input type="file" id="fileInput">
<button onclick="uploadFile()">Uploadbutton>
<script>
function uploadFile() {
const file = document.getElementById("fileInput").files[0];
const url = "/upload/o_upload";
const chunkSize = 1024 * 1024; // 每个块的大小(字节)
const fileSize = file.size; // 文件的总大小
const totalChunks = Math.ceil(fileSize / chunkSize); // 文件被分成的总块数
let chunkNumber = 0; // 当前上传的块的编号
let startByte = 0; // 当前上传块的起始字节位置
let endByte = chunkSize; // 当前上传块的结束字节位置(不包括)
uploadChunk();
function uploadChunk() {
const chunk = file.slice(startByte, endByte); // 获取当前上传块的内容
const formData = new FormData(); // 创建FormData对象
// 将参数添加到FormData对象中
formData.append("file", chunk);
formData.append("chunkNumber", chunkNumber);
formData.append("totalChunks", totalChunks);
formData.append("fileName", file.name);
formData.append("fileSize", fileSize);
// 创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
// 监听XMLHttpRequest对象的事件
xhr.onload = function() {
if (xhr.status === 200) {
// 上传成功,继续上传下一块
chunkNumber++;
startByte = endByte;
endByte = Math.min(startByte + chunkSize, fileSize);
if (startByte < fileSize) {
uploadChunk();
} else {
// 所有块上传成功
console.log("Upload completed");
}
} else {
// 上传失败,尝试重传当前块
console.error(xhr.statusText);
setTimeout(uploadChunk, 1000);
}
};
xhr.onerror = function() {
// 网络错误,尝试重传当前块
console.error(xhr.statusText);
setTimeout(uploadChunk, 1000);
};
// 发送POST请求
xhr.send(formData);
}
}
script>
body>
html>