php实现分片上传
PHP 实现分片上传的方法
分片上传(Chunked Upload)通常用于大文件上传,通过将文件分割成多个小块依次上传,可以避免单次上传大文件导致的超时或内存不足问题。以下是实现分片上传的关键步骤和代码示例。
前端实现分片切割与上传
前端需要使用 JavaScript 将文件分割成多个小块,并通过 AJAX 依次上传。以下是一个简单的实现示例:
// 选择文件后触发上传
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0];
const chunkSize = 1 * 1024 * 1024; // 每个分片大小为 1MB
const totalChunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
function uploadChunk() {
const start = currentChunk * 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('chunkIndex', currentChunk);
formData.append('totalChunks', totalChunks);
formData.append('fileName', file.name);
fetch('upload.php', {
method: 'POST',
body: formData
}).then(response => response.json())
.then(data => {
if (currentChunk < totalChunks - 1) {
currentChunk++;
uploadChunk();
} else {
console.log('上传完成');
}
});
}
uploadChunk();
});
后端 PHP 接收分片并合并
PHP 后端需要接收每个分片并临时保存,待所有分片上传完成后合并为一个完整的文件。
// upload.php
$targetDir = "uploads/tmp/";
$uploadDir = "uploads/";
$fileName = $_POST['fileName'];
$chunkIndex = $_POST['chunkIndex'];
$totalChunks = $_POST['totalChunks'];
// 确保临时目录存在
if (!file_exists($targetDir)) {
mkdir($targetDir, 0777, true);
}
// 临时分片文件名
$tmpFileName = $targetDir . $fileName . '.part' . $chunkIndex;
// 保存分片文件
move_uploaded_file($_FILES['file']['tmp_name'], $tmpFileName);
// 检查是否所有分片已上传完成
$allPartsUploaded = true;
for ($i = 0; $i < $totalChunks; $i++) {
if (!file_exists($targetDir . $fileName . '.part' . $i)) {
$allPartsUploaded = false;
break;
}
}
// 合并分片
if ($allPartsUploaded) {
$finalFile = $uploadDir . $fileName;
if ($fp = fopen($finalFile, 'wb')) {
for ($i = 0; $i < $totalChunks; $i++) {
$partFile = $targetDir . $fileName . '.part' . $i;
$content = file_get_contents($partFile);
fwrite($fp, $content);
unlink($partFile); // 删除临时分片
}
fclose($fp);
echo json_encode(['status' => 'success', 'message' => '文件上传完成']);
} else {
echo json_encode(['status' => 'error', 'message' => '无法创建最终文件']);
}
} else {
echo json_encode(['status' => 'processing', 'message' => '分片上传中']);
}
优化与注意事项
- 断点续传:记录已上传的分片索引,避免重复上传。
- 文件校验:合并完成后通过 MD5 或 SHA1 校验文件完整性。
- 清理临时文件:定期清理未完成的临时分片文件。
- 并发控制:限制同时上传的分片数量,避免服务器压力过大。
使用第三方库简化实现
如果需要更成熟的解决方案,可以考虑以下第三方库:

- Dropzone.js:支持分片上传的前端库。
- Resumable.js:专为分片上传设计的 JavaScript 库。
- Plupload:功能强大的文件上传库,支持分片上传。






