这里以PHP + JS 为例 ,简单代码,不过可以实现
前端代码
<form id="uploadForm">
<input type="file" id="file" name="file" />
<input type="button" value="点击上传" onclick="uploadFile()" />
</form>
<div class="card m-b-30">
<div class="card-body">
<div class="progress">
<div class="progress-bar" id="jdt" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div>
</div>
</div>
<script>
async function uploadFile() {
const file = document.getElementById('file').files[0];
const chunkSize = 1024 * 1024; // 每个分片的大小,这里以1MB为例
const totalChunks = Math.ceil(file.size / chunkSize); // 计算出来总共多少个分片
for (let i = 0; i < totalChunks; i++) {
const chunk = file.slice(chunkSize * i, i === totalChunks - 1 ? file.size : chunkSize * (i + 1));
const formData = new FormData();
formData.append('chunk', chunk); // 文件流二进制
formData.append('filename', file.name); // 文件名称
formData.append('chunked', true);
formData.append('chunkNumber', i + 1); // 分片的索引序号
formData.append('totalChunks', totalChunks); // 分片总数
const response = await fetch('bza/config/uploads', {
method: 'POST',
body: formData
});
const data = await response.json();
console.log(data)
if(data.status == 1){
// 显示进度条
const jdt = document.getElementById('jdt');
jdt.style.width = data.schedule + '%';
jdt.innerHTML = data.schedule + '%';
if(data.schedule == 100){
// 上传成功
}
}else{
alert('上传出错');
break;
}
}
}
</script>
php代码
public function uploads(){
// 分片上传
$targetDir = "./upload/bigfile/";
$fileName = $_POST['filename']; // 文件名称
$chunkIndex = $_POST['chunkNumber']; // 分片索引序号
$totalChunks = $_POST['totalChunks']; // 分片总数
$chunkFile = $targetDir . $fileName . '.part' . $chunkIndex; // 拼接分片文件路径/文件名称
$file = fopen($chunkFile, 'wb'); // 以二进制打开文件 准备对该文件进行写操作
if ($_FILES['chunk']['error'] === 0) {
// 如果上传的文件0错误
$data = file_get_contents($_FILES['chunk']['tmp_name']); // 读取文件内容并且写入
fwrite($file, $data);
}
fclose($file); // 写入成功 关闭文件
// 检查所有分块是否上传完毕,并合并
if ($chunkIndex === $totalChunks) {
$file = fopen($targetDir . $fileName, 'wb'); // // 以二进制打开文件 准备对该文件进行写操作
for ($i = 1; $i <= $totalChunks; $i++) {
$chunk = file_get_contents($targetDir . $fileName . '.part' . $i); // 循环读取分片文件
fwrite($file, $chunk); // 写入源文件
unlink($targetDir . $fileName . '.part' . $i); // 写入成功 删除分片文件
}
fclose($file); // 关闭文件
}
// 返回上传进度 根据分片 已上传 / 总数 = 进度
$schedule = sprintf("%.2F",($chunkIndex / $totalChunks) * 100);
if($schedule == 100){
echo json_encode(['status' => 1,'msg'=>'success','schedule'=>$schedule,'path'=>$targetDir . $fileName],JSON_UNESCAPED_UNICODE);
exit;
}
echo json_encode(['status' => 1,'msg'=>'success','schedule'=>$schedule],JSON_UNESCAPED_UNICODE);
}