多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## javascript ~~~ // 分片上传函数 ~~~ ~~~ async function uploadFile(file) { if (!file || typeof file !== 'object') { console.error('Invalid file object'); return; } const chunkSize = 1024 * 1024 * 2; // 分片大小,这里设置为2MB const totalChunks = Math.ceil(file.size / chunkSize); // 总分片数 let currentChunk = 0; // 当前分片序号 // 将文件分片 const chunks = []; 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); chunks.push(chunk); } // 上传分片 for (const chunk of chunks) { let formData = new FormData(); formData.append('file', chunk); formData.append('chunkIndex', currentChunk); formData.append('totalChunks', totalChunks); formData.append('file_name', file_count +'_'+file.name); try { const response = await axios.post('./upload.php', formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); document.querySelector('.spinner-border').style.display = 'none' let progress = response.data.progress if (response.data.success) { if(response.data.status == 'error'){ alert(response.data.msg) return } set_progress(progress) if (response.data.status === 'end'){ is_upload = false set_progress(100) console.log(`分片上传成功完毕`); setTimeout(()=>{ location.reload() },500) return } currentChunk++; console.log(`分片${currentChunk}上传成功`); } else { break; //console.error(`分片${currentChunk}上传失败`); } } catch (error) { console.error(`分片${currentChunk}上传出错`, error); throw error; } } } ~~~ ~~~ //点击开始上传 const form = document.getElementById('file-upload-form'); const fileInput = document.getElementById('file-input'); form.addEventListener('submit', function(event) { if (is_upload) return event.preventDefault(); if (fileInput.files && fileInput.files[0]) { is_upload = true document.querySelector('.spinner-border').style.display = 'block' const file = fileInput.files[0]; uploadFile(file); } else { alert('请选择文件!') } }); ~~~ ## html ~~~ <form id="file-upload-form" method="post" enctype="multipart/form-data"> <input accept="video/*" id="file-input" class="btn btn-light" type="file" name="file"><br> <br> <button type="submit" class="btn btn-primary">开始上传</button> </form> ~~~ ## php ~~~ // 获取请求中的分片信息 $chunkIndex = (int) trim($_POST['chunkIndex']); $totalChunks = (int) trim($_POST['totalChunks']); $file_name = $_POST['file_name']; $file = $_FILES['file']; //status:error 错误 //status:end 已上传 if (!strstr($file_name,'.')){ echo json_encode(['success'=> 'ok','msg'=>'不允许的文件!','status'=> 'error','progress' => 0]); return; } $exit = explode('.', $file_name); $exit = end($exit); //白名单 $fillable_exit = ['mp4','fly','avi','wmv','mov']; if (!in_array(strtolower($exit), $fillable_exit)){ echo json_encode(['success'=> 'ok','msg'=>'不允许的文件!','status'=> 'error','progress' => 0]); return; } // 计算分片文件的临时存储路径 $tempPath = 'temp/' . $file['name'] . '.txt'; $targetPath = 'uploads/'. $file_name; if (file_exists(__DIR__ .'/'. $targetPath) && $chunkIndex == 0){ echo json_encode(['success'=> 'ok','msg'=>'此文件已上传','status'=> 'error','progress' => 0]); return; } // 将当前分片移动到临时存储路径 move_uploaded_file($file['tmp_name'], $tempPath); //计算进度条 $persent = number_format($chunkIndex / $totalChunks * 100,1); // 检查是否所有分片都已上传 if ($chunkIndex == $totalChunks - 1) { // 将所有分片合并为一个完整的文件 $outputPath = $targetPath; for ($i = 0; $i < $totalChunks; $i++) { try { $outputFile = fopen($outputPath, 'ab'); $inputFile = fopen($tempPath, 'rb'); while (!feof($inputFile)) { fwrite($outputFile, fread($inputFile, filesize($tempPath))); } fclose($inputFile); fclose($outputFile); unlink($tempPath); // 删除临时文件 echo json_encode(['success'=>1,'msg'=>'ok','status'=>'end','progress' => $persent]);exit; }catch (Exception $e){} } } else { // 如果还有其他分片未上传,将当前分片追加到目标文件中 $outputFile = fopen($targetPath, 'ab'); $inputFile = fopen($tempPath, 'rb'); while (!feof($inputFile)) { fwrite($outputFile, fread($inputFile, filesize($tempPath))); } fclose($inputFile); fclose($outputFile); echo json_encode(['success'=>1,'msg'=>'ok','status'=>'up','progress' => $persent]); } ~~~