javascript - 通过javascript将大文件上传到服务器
问题描述
使用 javascript 和 ajax 将任何类型的技嘉文件(例如:视频、音频、图像、文档)上传到 php 服务器的最佳方式是什么?
将文件作为分块 blob发送?
还是先将blob转换为ArrayBuffer然后发送到 php?
将文件作为 ArrayBuffer发送时如何在服务器端合并文件?
文件到blob函数:
function sliceFile(file, chunksAmount) {
var byteIndex = 0;
var chunks = [];
for (var i = 0; i < chunksAmount; i += 1) {
var byteEnd = Math.ceil((file.size / chunksAmount) * (i + 1));
chunks.push(file.slice(byteIndex, byteEnd));
byteIndex += (byteEnd - byteIndex);
}
return chunks;
}
作为ArrayBuffer函数发送:
function sendChunkFile(chunksArray,filename){
var slice_chunk = chunksArray.shift();
var reader = new FileReader();
reader.onload = function(event){
var fd = new FormData();
fd.append('filename', filename);
fd.append('data', event.target.result);
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
if(chunksArray.length){
sendChunkFile(chunksArray,filename)
}
});
};
reader.readAsArrayBuffer(slice_chunk);
}
解决方案
在客户端:
步骤1 :
制作Blob 切片:
切片功能
function slice(file, start, end) {
var slice = file.mozSlice ? file.mozSlice :
file.webkitSlice ? file.webkitSlice :
file.slice;
return slice.bind(file)(start, end);
}
文件切片器
function sliceFile(file, chunksAmount, mimetype) {
var byteIndex = 0;
var chunks = [];
for (var i = 0; i < chunksAmount; i += 1) {
var byteEnd = Math.ceil((file.size / chunksAmount) * (i + 1));
chunks.push( new Blob([slice(file, byteIndex, byteEnd)], {
type: mimetype
}));
byteIndex += (byteEnd - byteIndex);
}
return chunks;
}
文件切片器助手
function chunksAmount(size){
const BYTES_PER_CHUNK = ((1024 * 1024)*5); //5MB chunk sizes.
return Math.ceil(size / BYTES_PER_CHUNK);
}
获取 Blob
var file = self.get(0).files.item(0); //files[0];
var chunks = chunksAmount(file.size);
var blobChunksArray = sliceFile(file,chunks,file.type);
第2步 :
将Blob发送到服务器端:
发送功能
function sendChunkFile(chunksArray,filename){
var slice_chunk = chunksArray.shift();
var fd = new FormData();
fd.append('chunksupload',true);
fd.append('filename', filename);
fd.append('data', slice_chunk);
if(chunksArray.length){
fd.append('chunksend',false);
}else{
fd.append('chunksend',true);
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
if(chunksArray.length){
sendChunkFile2(chunksArray,filename)
}else{
console.log(JSON.stringify(data));
}
});
}
第 3 步:
通过PHP处理Blob到服务器端
<?php
if(isset($_POST['chunksupload'])){
file_put_contents($_POST['filename'], file_get_contents($_FILES['data']['tmp_name']), FILE_APPEND | LOCK_EX);
if($_POST['chunksend']){
echo json_encode(["url"=>"path-to-file/".$_POST['filename'],"size"=>filesize($_POST['filename']) . " bytes"]);
}else{
return true;
}
}
return false;
推荐阅读
- logging - 在 Kubernetes 属性上使用 Fluent Bit Modify Filter
- xamarin - 访问 .Net 标准项目库中的 Application.Current
- java - 将具有 NULL 值的本机查询结果转换为 POJO
- javascript - Firebase 使用效果重新渲染
- c# - 如何检查 catch 块中抛出的异常类型?
- python - 如何使用 python 读取 excel 上的数据,然后将单元格等同于不同的变量,例如。x、y、z 等
- numpy - 从 numpy 行向量中每第 5 和第 6 个元素切片
- javascript - 展开和折叠下拉菜单
- angular - 是否可以在角度的 ag 网格单元中添加多选下拉
- excel - 基于单元格值的行数(循环复制)