ajax上传大文件blob传到后端
时间: 2025-01-04 17:34:02 浏览: 13
### 实现大文件上传的最佳实践
为了实现通过Ajax以Blob形式传输大文件到后端,前端和后端都需要精心设计来确保高效、稳定的数据传输。下面将详细介绍这一过程。
#### 前端部分
在前端方面,使用JavaScript中的`FileReader`对象读取文件并将其转换成Blob格式。接着利用XMLHttpRequest (XHR) 或者更现代的Fetch API发送请求。考虑到大型文件可能会超出服务器设定的时间限制,推荐采用分片上传的方式减少每次请求的数据量[^2]。
```javascript
function uploadFile(file, chunkSize = 10 * 1024 * 1024 /* 10MB */) {
let start = 0;
const totalChunks = Math.ceil(file.size / chunkSize);
function sendChunk(chunkIndex) {
if (chunkIndex >= totalChunks) return;
const end = ((chunkIndex + 1) * chunkSize > file.size ? file.size : (chunkIndex + 1) * chunkSize);
const blob = file.slice(start, end); // 创建blob片段
fetch('/upload', {
method: 'POST',
headers: { "X-Chunks": `${chunkIndex}/${totalChunks}` },// 添加额外头信息用于指示当前是第几个碎片以及总共有多少个碎片
body: new FormData().append('file', blob),
}).then(response => response.json())
.then(data => console.log(`Uploaded chunk ${chunkIndex}`, data))
.catch(error => console.error('Error:', error));
start += chunkSize; // 更新起始位置以便于下一次调用sendChunk函数时继续处理下一个fragment.
setTimeout(() => sendChunk(++chunkIndex), 500); // 设置延迟防止过快触发网络拥塞等问题。
}
sendChunk(0);
}
```
此代码段展示了如何创建一个名为`uploadFile()`的功能函数,该函数接受要上传的文件作为参数,并按照指定大小分割文件为多个blobs进行逐块上传。注意这里还设置了合理的等待时间间隔以避免过多并发连接造成的服务压力。
对于FormData对象,在构建HTTP POST请求体之前会自动序列化表单字段及其关联值;而设置`processData:false`与`contentType:false`则告诉jQuery不要尝试去解析提交的内容类型或编码方式,这对于二进制数据尤为重要[^4]。
#### 后端部分
后端接收这些零碎化的文件部分并将它们重新组合起来。这通常涉及到保存临时文件直到所有预期的部分都到达为止。一旦确认整个文件已被成功接收到,则可以执行进一步的动作比如验证完整性或将最终版本移动到永久存储位置。
以下是基于Spring框架的一个简化版控制器示例:
```java
@PostMapping("/upload")
public ResponseEntity<String> handleFileUpload(@RequestPart MultipartFile file,
@RequestHeader(value="X-Chunks") String chunksInfo){
try{
int currentChunk = Integer.parseInt(chunksInfo.split("/")[0]);
int totalChunks = Integer.parseInt(chunksInfo.split("/")[1]);
Path tempFilePath = Files.createTempFile("temp-", ".part");
Files.copy(file.getInputStream(), tempFilePath, StandardCopyOption.REPLACE_EXISTING);
// 将每个接收到的小块追加到目标路径下的同一文件中...
File targetFile = new File("path/to/final/file.ext");
RandomAccessFile raf = null;
FileOutputStream fos = null;
try {
raf = new RandomAccessFile(targetFile, "rw");
long seekPosition = (long)(currentChunk - 1) * CHUNK_SIZE_IN_BYTES;
raf.seek(seekPosition);
byte[] buffer = Files.readAllBytes(tempFilePath);
fos = new FileOutputStream(targetFile, true);
fos.write(buffer);
} finally {
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(raf);
}
if(currentChunk == totalChunks){
// 所有分片已全部接收完毕,此时可做校验或其他操作
return ResponseEntity.ok("Complete!");
}else{
return ResponseEntity.accepted().body(String.format("Received %d/%d", currentChunk, totalChunks));
}
} catch(Exception e){
log.error(e.getMessage());
throw new RuntimeException("Failed to process uploaded part.");
}
}
```
这段Java代码定义了一个RESTful Web服务端点,它能够处理来自客户端发出的一系列带有特定头部标记(即`X-Chunks`)的multipart/form-data类型的POST请求。每当一个新的文件片段被传入时,都会先存放到系统的临时目录里再逐步拼接到预设的目标地址上形成完整的副本[^3]。
阅读全文