刚开始直接对file源文件进行的slice切片,但是这样的切片到后端处理着稍微有点麻烦,所以我就试着用base64进行切片,效果很不错,减少了工作量,也提高了效率。
思路
先用jquery对文件进行base64转换,得到base64编码,然后计算base64的长度,用slice方法每次截取固定的长度,放到数组中,然后循环数组的同时把base64切片依次传到后端,在后端可以把切片临时存储到cookie或者session中,当然redis之类的技术也可以,哪个方便用哪个,到最后把所有切片拼接起来,可以通过oss传到对象服务器或者其他地方,这都不用多说了。
代码实现
jquery前端切片实现代码:
//图片转base64
function BlobToBase64(blob) {
return new Promise(function (resolve) {
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function () {
resolve(this.result)
}
})
}
//转化base64格式
BlobToBase64(file).then((res) => {
var arr = [];
//设置每个切片的长度
const ChunkSize = 1024 * 1024 * 3;
//截取开始的位置
var start = 0;
//截取结束的位置
var end = ChunkSize;
while (start < res.length) {
//截取出来的字符串放到arr中
arr.push(res.slice(start, end))
start = end;
end = start + ChunkSize;
}
//设置当前传给后端的切片序号
var file_index = 0;
//循环切片,依次传给后端
arr.map((itm, idx) => {
file_index++;
$.post("Your Url", {
base64: itm,
file_index: file_index,
total: arr.length //切片总数
}, function (res) {
})
})
})
php后端接收切片代码:
/**
* 文件上传.
*
* @return [type] [description]
*/
public function uploadfile()
{
try {
$post = $_POST;
$imageBase64Data = $post['base64'];
//把接收到的切片临时存储到session中,以数组的形式,键名为前端传过来的切片序号,键值为切片内容,当然这里建议用其它方式存储,比如redis之类的
$_SESSION['upload_base64'][$post['file_index']] = $imageBase64Data;
//存储接收到的切片总数
$_SESSION['upload_base64_total']++;
//判断接收到的切片总数是否等于前端传过来的切片总数,如果不等于则返回一个上传进度
if ($_SESSION['upload_base64_total'] != ($post['total'])) {
$percent = $_SESSION['upload_base64_total'] / ($post['total']);
if ($percent>1){
$_SESSION['upload_base64_total'] = 0;
$_SESSION['upload_base64'] = [];
}
return ['code' => 2, 'msg' => '上传进度' . ($percent * 100) . "%"];
}
//根据切片序号进行排序,因为jquery是异步执行的,所以顺序可能是乱的
ksort($_SESSION['upload_base64']);
$upload_base64 = '';
//循环拼接出原始的base64编码
foreach ($_SESSION['upload_base64'] as $base64) {
$upload_base64 .= $base64;
}
//清空session
$_SESSION['upload_base64_total'] = 0;
$_SESSION['upload_base64'] = [];
//这里用的阿里云的OSS、base64的上传方式
$oss = new Oss();
$res = $oss->uploadFileBase64($upload_base64, time() . rand(9999, 999999) . $post['filename']);
if ($res['code'] == 0) {
$url = $res['url'];
} else {
return json($res);
}
$data = [
"code" => 0,
"msg" => "上传成功",
"data" => $url
];
} catch (\Exception $e) {
$data = ['code' => -1, 'msg' => $e->getMessage()];
}
return $data;
}