要在上传文件时使用 chunked 传输编码(Transfer-Encoding: chunked)将文件分块传输给上游服务器,你需要在前端和后端都进行相应配置。以下是完整解决方案:
前端修改(纯HTML无法直接控制)
由于HTML表单本身无法直接控制chunked传输,需要通过JavaScript实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chunked Upload Demo</title>
</head>
<body>
<input type="file" id="fileInput">
<button onclick="uploadFile()">提交</button>
<script>
async function uploadFile() {
const file = document.getElementById('fileInput').files[0];
if (!file) return;
const chunkSize = 1024 * 1024; // 1MB每块
const totalChunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
await fetch('/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'X-Chunk-Index': i,
'X-Total-Chunks': totalChunks,
'X-File-Name': encodeURIComponent(file.name),
'X-File-Size': file.size
},
body: chunk
});
console.log(`Uploaded chunk ${i + 1}/${totalChunks}`);
}
console.log('Upload complete!');
}
</script>
</body>
</html>
后端处理示例(Node.js版)
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
app.use(express.json());
app.post('/upload', async (req, res) => {
try {
const fileName = decodeURIComponent(req.headers['x-file-name']);
const tempDir = './temp';
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir);
}
const tempFilePath = path.join(tempDir, fileName + '.part');
// 追加写入分块数据
req.on('data', chunk => {
fs.appendFileSync(tempFilePath, chunk);
});
req.on('end', () => {
if (parseInt(req.headers['x-chunk-index']) === parseInt(req.headers['x-total-chunks']) - 1) {
// 如果是最后一个分块则重命名文件
fs.renameSync(tempFilePath, path.join(tempDir, fileName));
res.status(200).send('Upload complete');
} else {
res.status(200).send('Chunk received');
}
});
} catch (err) {
res.status(500).send(err.message);
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
关键点说明:
前端实现:
- 使用
fetch API
和Blob.slice()
方法手动分块 - 每个分块通过独立的HTTP请求发送
- 使用
后端实现:
- Node.js会自动处理chunked传输编码的请求体
- 通过监听
data
事件获取分片数据
注意事项:
- Nginx默认支持chunked传输,但可能需要调整
client_max_body_size
- Tomcat等Java容器需要确保配置了
maxSwallowSize
- Nginx默认支持chunked传输,但可能需要调整
如果需要完整的商业级解决方案,零声教育提供包含以下内容的高性能网络课程:
- HTTP协议深度解析
- Chunked传输编码优化
- 断点续传实现
- 大文件上传加速方案
内容由零声教学AI助手提供,问题来源于学员提问