摘要
视频文件分片上传,整体思路是利用JavaScript将文件切片,然后循环调用上传接口 upload.php
将切片上传到服务器。这样将由原来的一个大文件上传变为多个小文件同时上传,节省了上传时间,这就是文件分片上传的其中一个好处。
上代码
index.html
通过前端将文件对象切分成多个小块,然后依次将这些小块的文件对象上传到服务器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | < title >视频文件分片上传</ title > *{ padding: 0; margin: 0; } .title { text-align: center; font-size: 25px; margin-top: 50px; } .video_upload { width: 500px; height: 60px; background: #eee; margin: 30px auto 0; border: 2px dashed #ccc; border-radius: 10px; position: relative; cursor: pointer; text-align: center; font-size: 25px; line-height: 60px; color: #666; } #fileInput { width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; cursor: pointer; } #uploadButton { width: 130px; height: 40px; border: none; outline: none; border-radius: 10px; font-size: 17px; margin: 10px auto; } #ret { text-align: center; font-size: 16px; margin-top: 20px; } #ret video { width: 450px; } < p class = "title" >javaScript+PHP实现视频文件分片上传</ p > < div class = "video_upload" > < span class = "text" > + </ span > </ div > < button id = "uploadButton" >开始上传</ button > < p id = "ret" ></ p > // 定义全局变量 let videoFile = null; let chunkSize = 1024 * 1024; // 1MB 分片大小 // 当文件选择框的值改变时触发该函数 function handleFileSelect(event) { const fileList = event.target.files; if (fileList.length > 0) { videoFile = fileList[0]; console.log("选择了文件: ", videoFile.name); document.querySelector('.video_upload .text').textContent = videoFile.name; document.querySelector('#uploadButton').style.display = 'block'; } } // 分片并上传文件 async function uploadFile() { if (!videoFile) { console.error("请选择一个视频文件"); return; } const fileSize = videoFile.size; let start = 0; let end = Math.min(chunkSize, fileSize); let chunkIndex = 0; // 获取文件名 const fileName = videoFile.name; while (start < fileSize ) { const chunk = videoFile .slice(start, end); // 从文件中截取一个分片 // 使用FormData来构建multipart/form-data格式的请求体 const formData = new FormData(); formData.append('file', chunk); formData.append('chunkIndex', chunkIndex); formData.append('fileName', fileName); // 将文件名作为 formData 的一部分 try { const response = await fetch('upload.php', { method: 'POST', body: formData }); if (!response.ok) { throw new Error('上传失败'); } console.log('上传分片 ', chunkIndex, ' 成功'); } catch (error) { console.error('上传分片 ', chunkIndex, ' 失败: ', error.message); return; } start = end ; end = Math .min(start + chunkSize, fileSize); chunkIndex++; } console.log('文件上传完成'); // 上传完成后发送通知给服务器进行合并 notifyServerForMerge(fileName); } // 发送通知给服务器进行合并 async function notifyServerForMerge(fileName) { try { const response = await fetch('merge_chunks.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fileName: fileName }) }); if (!response.ok) { throw new Error('无法通知服务器进行合并'); } const res_data = await response.json(); console.log('已通知服务器进行合并'); document.querySelector('.video_upload .text') .textContent = '分片合并完成!' ; document.querySelector('#ret') .innerHTML = '<video autoplay="" controls="" src="' +res_data.filePath+'" data-origwidth = "0" data-origheight = "0" style = "width: 1264px;" >'; document.querySelector('#uploadButton').style.display = 'none'; } catch (error) { console.error('通知服务器进行合并时发生错误: ', error.message); } } // 注册文件选择框的change事件 document.getElementById('fileInput').addEventListener('change', handleFileSelect); // 注册上传按钮的click事件 document.getElementById('uploadButton').addEventListener('click', uploadFile); </ video > |
upload.php
这个是用于接收前端传过来的每一段分片,然后上传到 uploads
文件夹,上传之后就是一段一段的小分片。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | '文件上传失败' )); exit (); } // 设置存储目录和文件名 $uploadDir = './uploads/' ; $filePath = $uploadDir . $fileName . '.' . $chunkIndex ; // 将分片移动到指定的目录 if (move_uploaded_file( $_FILES [ 'file' ][ 'tmp_name' ], $filePath )) { echo json_encode( array ( 'success' => '分片上传成功' )); } else { http_response_code(500); echo json_encode( array ( 'error' => '分片上传失败' )); } } else { http_response_code(400); echo json_encode( array ( 'error' => '缺少文件、分片索引或文件名' )); } ?> |
merge_chunks.php
这个是用来合并分片的,当前端完成上传分片的操作,前端会异步告诉服务器你已经完成所有分片的上传,接下来将每个分片名告诉合并程序完成所有分片的合并,合并之后就是一个完整的视频文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 0) { // 所有分片都已上传,开始合并 $finalFile = fopen ( $finalFilePath , 'wb' ); // 逐个读取分片并写入最终文件 for ( $i = 0; $i '文件合并成功' , 'filePath' => $finalFilePath )); } else { http_response_code(400); echo json_encode( array ( 'error' => '没有上传的分片' )); } } else { http_response_code(400); echo json_encode( array ( 'error' => '缺少文件名' )); } ?> |
程序目录
请自行创建 uploads
目录。
以上就是JavaScript+PHP实现视频文件分片上传的示例代码的详细内容,更多关于JavaScript+PHP视频文件上传的资料请关注IT俱乐部其它相关文章!