实现文件的断点续传需要前后端配合完成,前端使用JavaScript实现文件的分片和上传,后端使用PHP接收上传的分片并拼接成完整文件。
前端实现
文件分片
为了避免上传过大的文件造成浏览器崩溃或网络中断,前端需要将文件切分成多个小的分片进行上传。可以使用File API中的FileReader对象和Blob对象来实现,具体实现可参考以下代码:
function sliceFile(file, start, end) {
var reader = new FileReader();
var blob = file.slice(start, end);
reader.readAsArrayBuffer(blob);
reader.onload = function(e) {
// do something with loaded data
};
}
其中,file为需要分片的文件对象,start和end为开始和结束的字节位置。
上传分片
上传分片需要使用XMLHttpRequest对象发送POST请求,请求的数据为二进制数据而不是FormData对象。并且在请求头中需设定Content-Type为multipart/form-data,可以参考以下代码:
function uploadSlice(slice, url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(xhr.responseText);
}
};
xhr.send(slice);
}
其中,slice为需要上传的二进制数据,url为上传的后端接口地址,callback为上传成功后的回调函数。
断点续传
为了实现断点续传,前端需要记录上传的分片信息,包括上传的进度、已上传的分片等信息。这些信息可以存储在客户端本地或服务器端,具体可根据实际场景进行决定。
以下是一个示例实现断点续传的代码:
function uploadFile(file, url) {
var chunkSize = 1024 * 1024; // 1MB
var chunks = Math.ceil(file.size / chunkSize);
var currentChunk = 0;
var startTime = new Date().getTime();
var progress = 0;
var uploadedChunks = [];
function uploadNextChunk() {
var start = currentChunk * chunkSize;
var end = Math.min((currentChunk + 1) * chunkSize, file.size);
sliceFile(file, start, end, function(data) {
uploadSlice(data, url, function(res) {
uploadedChunks.push(currentChunk);
currentChunk++;
progress = Math.round((currentChunk / chunks) * 100);
if (currentChunk < chunks) {
uploadNextChunk();
} else {
var endTime = new Date().getTime();
var duration = (endTime - startTime) / 1000;
console.log("上传完成,总用时:" + duration + "秒");
}
});
});
}
// check if there are uploaded chunks
if (localStorage.getItem(file.name)) {
uploadedChunks = JSON.parse(localStorage.getItem(file.name));
currentChunk = uploadedChunks[uploadedChunks.length - 1] + 1;
progress = Math.round((currentChunk / chunks) * 100);
}
uploadNextChunk();
}
其中,chunkSize为每个分片的大小,chunks为总共需要上传的分片数,currentChunk为当前已经上传的分片数,startTime为上传开始的时间,progress为上传的进度百分比。如果之前已经上传过部分分片,则从localStorage中读取已上传的分片信息,并从上次的位置继续上传。
后端实现
分片接收
为了接收上传的分片,后端需要实现一个接口,接收POST请求,并将二进制数据保存成文件。
以下是一个示例的PHP代码:
$fileName = $_POST['fileName'];
$chunkIndex = $_POST['chunkIndex'];
if (!empty($_FILES['chunk'])) {
$chunk = file_get_contents($_FILES['chunk']['tmp_name']);
file_put_contents('./uploads/' . $fileName . '.part' . $chunkIndex, $chunk);
echo 'chunk received';
}
其中,fileName和chunkIndex为上传的分片信息。
分片合并
当所有的分片都上传完成后,后端需要将它们合并成完整的文件。以下是一个示例的PHP代码:
$fileName = $_POST['fileName'];
$totalChunks = $_POST['totalChunks'];
$file = fopen('./uploads/' . $fileName, 'wb');
for ($i = 0; $i < $totalChunks; $i++) {
fwrite($file, file_get_contents('./uploads/' . $fileName . '.part' . $i));
unlink('./uploads/' . $fileName . '.part' . $i);
}
fclose($file);
echo 'file merged';
其中,fileName为上传的文件名,totalChunks为上传的总分片数。在合并分片时,需要按照片段的序号从小到大依次读取分片的内容并写入完整的文件中,最后删除已合并的片段。
示例说明
以下是一个示例项目,实现了前端使用JavaScript实现文件的断点续传、后端使用PHP接收分片上传并拼接成完整文件的功能:https://github.com/xiaowu-fe/file-upload-demo
该项目使用了Web Workers来实现文件分片和上传,可以方便地实现大文件的上传。另外,也包括了文件MD5校验和秒传的逻辑,可以减少重复上传的文件,提高上传效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:前端js实现文件的断点续传 后端PHP文件接收 - Python技术站