Java 大文件分片上传前后端代码实现
选择文件
上传进度
<script>
// 上传文件的起始位置
var start = 0;
// 分片大小(5MB)
var chunkSize = 5 * 1024 * 1024;
// 上传文件的总大小
var fileSize = 0;
// 上传文件的分片总数
var totalChunks = 0;
// 当前上传的分片
var currentChunk = 0;
// 文件对象
var file = null;
// 上传文件的唯一标识符
var uploadId = null;
// 选择文件
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function (event) {
file = event.target.files[0];
fileSize = file.size;
totalChunks = Math.ceil(fileSize / chunkSize);
console.log('文件大小:' + fileSize);
console.log('分片总数:' + totalChunks);
});
function startUpload() {
// 发送请求,获取上传文件的唯一标识符
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getUploadId?fileName=' + file.name + '&fileSize=' + fileSize);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
uploadId = xhr.responseText;
console.log('上传文件的唯一标识符:' + uploadId);
// 开始上传文件的第一个分片
uploadChunk();
}
};
xhr.send();
}
function uploadChunk() {
// 计算当前分片的起始位置和结束位置
var chunkStart = start + currentChunk * chunkSize;
var chunkEnd = Math.min(chunkStart + chunkSize, fileSize);
var chunk = file.slice(chunkStart, chunkEnd);
// 发送分片上传请求
var xhr = new XMLHttpRequest();
xhr.open('POST', '/uploadChunk');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.setRequestHeader('X-Upload-Id', uploadId);
xhr.setRequestHeader('X-Chunk-Number', currentChunk + 1);
xhr.setRequestHeader('X-Total-Chunks', totalChunks);
xhr.setRequestHeader('X-Chunk-Size', chunkSize);
xhr.setRequestHeader('X-File-Name', file.name);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log('上传分片成功:' + xhr.responseText);
// 更新上传进度
var progress = Math.round((chunkEnd / fileSize) * 100);
document.getElementById('progressBar').value = progress;
// 如果还有下一个分片,则继续上传
if (currentChunk + 1 < totalChunks) {
currentChunk++;
uploadChunk();
}
}
};
xhr.send(chunk);
}
</script>
```java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 存储上传文件的目录
private static final String UPLOAD_DIR = 'uploads/';
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取上传文件的唯一标识符
String fileName = request.getParameter('fileName');
long fileSize = Long.parseLong(request.getParameter('fileSize'));
String uploadId = UUID.randomUUID().toString();
// 创建分片上传记录文件
Path path = Paths.get(UPLOAD_DIR + fileName + '.' + uploadId);
Files.createFile(path);
// 返回分片上传记录文件的唯一标识符
response.getWriter().write(uploadId);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取上传文件的唯一标识符、分片编号、分片总数、分片大小、文件名
String uploadId = request.getHeader('X-Upload-Id');
int chunkNumber = Integer.parseInt(request.getHeader('X-Chunk-Number'));
int totalChunks = Integer.parseInt(request.getHeader('X-Total-Chunks'));
int chunkSize = Integer.parseInt(request.getHeader('X-Chunk-Size'));
String fileName = request.getHeader('X-File-Name');
// 获取上传文件的分片
InputStream inputStream = request.getInputStream();
byte[] chunk = inputStream.readAllBytes();
// 将上传文件的分片写入临时文件
Path path = Paths.get(UPLOAD_DIR + fileName + '.' + uploadId);
try (OutputStream outputStream = new FileOutputStream(path.toFile(), true)) {
outputStream.write(chunk);
}
// 如果是最后一个分片,则合并分片为完整的上传文件
if (chunkNumber == totalChunks) {
// 从临时文件读取上传文件的所有分片
byte[] fileBytes = Files.readAllBytes(path);
// 删除临时文件
Files.delete(path);
// 创建上传文件的目录(如果不存在)
Path uploadPath = Paths.get(UPLOAD_DIR);
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}
// 写入完整的上传文件
Path filePath = Paths.get(UPLOAD_DIR + fileName);
Files.write(filePath, fileBytes);
// 返回上传成功信息
response.getWriter().write('上传成功');
} else {
// 返回上传分片成功信息
response.getWriter().write('上传分片成功');
}
}
}
说明:
- 前端代码通过文件选择框选择要上传的文件,然后将文件分成多个分片上传,每个分片大小为5MB。
- 前端代码通过XMLHttpRequest对象发送GET请求,获取上传文件的唯一标识符。然后通过XMLHttpRequest对象发送POST请求,上传文件的每个分片。
- 后端代码根据文件名、文件大小和随机生成的UUID创建一个分片上传记录文件,文件名格式为
<文件名>.<上传文件的唯一标识符>。每次上传分片时,将分片写入分片上传记录文件。如果是最后一个分片,则将所有分片合并成完整的上传文件,并将上传文件存储到uploads/目录下。 - 上传文件的唯一标识符、分片编号、分片总数、分片大小和文件名通过HTTP请求头传递。
原文地址: https://www.cveoy.top/t/topic/nPEN 著作权归作者所有。请勿转载和采集!