关于大文件上传
栏目: JavaScript · 发布时间: 5年前
内容简介:最近在做视频上传,我们使用切片上传大文件,做个笔记。js计算文件md5使用js对文件切片并使用ajax上传切片
最近在做视频上传,我们使用切片上传大文件,做个笔记。
思路
- 使用js读取form表单中选择的file,计算文件md5值,并上传md5值到服务端,检查文件是否已上传过(类似秒传功能)
- 若文件未上传过,按照其大小切成1MB大小的块,小于1MB的不用切
- 用ajax异步提交切好的块上传至服务端(一个块一个请求,不阻塞,多线程)
- 当上传完成所有切块,发起一个合并文件的请求,服务端进行前面上传的文件块的合并,合并完成即上传完成。
实现
js计算文件md5使用 spark-md5.js ,据说这个库使用的是世界上最快的md5算法。
js对文件切片并使用ajax上传切片
//... let size = file.size; //获取文件大小 const shardSize = 1024 * 1024; // 块大小1MB let shardCount = Math.ceil(size/shardSize); //可切成的块数 for(let i = 0; i < shardCount; i++){ let start = i * shardSize, end = Math.min(size, start + shardSize); let form = new FormData(); form.append('file', file.slice(start, end)); //用slice方法切片 form.append('size', end - start); form.append('name', name); form.append('total', shardCount); form.append('md5', file_md5); //文件md5值 form.append('index', i); //第几块 $.ajax({ url: 'upload.php?type=shard', type: "POST", data: form, // async: false, //是否异步上传,默认true processData: false, //很重要,告诉jquery不要对form进行处理 contentType: false, //很重要,指定为false才能形成正确的Content-Type success: function (res) { // 成功回调 } } }
php端保存切片
$path = __DIR__ . '/uploads'; $file = $_FILES['file']; $total = $_POST['total']; $index = $_POST['index']; $size = $_POST['size']; $dst_file = $path . '/' . $name . '-' . $total . ':' . $index; // 切片文件存储的文件名 if ($file["error"] > 0) { echo json_encode(['code'=>400, 'msg'=>$file["error"]]);die; } else { $res = move_uploaded_file($file['tmp_name'], $dst_file); if ($res) { file_put_contents($dst_file . '.info', $size); // 切片上传成功,写一个保存其大小的文件,后续合并是校验文件用的到 echo json_encode(['code'=>200, 'msg'=>'shard ok']);die; } else { echo json_encode(['code'=>400, 'msg'=>'shard move_uploaded_file error']);die; } }
php端合并
//... function mergeFile($name, $total, &$msg) { // 校验切片文件是否都上传完成,是否完整 for ($i = 0; $i < $total; $i++) { if (!file_exists($name . '-' . $total . ':' . $i . '.info') || !file_exists($name . '-' . $total . ':' . $i)) { $msg = "shard error $i"; return false; } else if (filesize($name . '-' . $total . ':' . $i) != file_get_contents($name . '-' . $total . ':' . $i . '.info')) { $msg = "shard size error $i"; return false; } } @unlink($name); if (file_exists($name . '.lock')) { //加锁 防止有其他进程写文件,造成文件损坏 $msg = 'on lock'; return false; } touch($name . '.lock'); $file = fopen($name, 'a+'); for ($i = 0; $i < $total; $i++) { //按切片顺序写入文件 $shardFile = fopen($name . '-' . $total . ':' . $i, 'r'); $shardData = fread($shardFile, filesize($name . '-' . $total . ':' . $i)); fwrite($file, $shardData); fclose($shardFile); unlink($name . '-' . $total . ':' . $i); unlink($name . '-' . $total . ':' . $i . '.info'); } fclose($file); unlink($name . '.lock'); return true; }
我也写好了一个demo, 传送门
下面是这个demo的效果图:
这个demo有些方面还不够完善,后续持续完善吧~
以上所述就是小编给大家介绍的《关于大文件上传》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
CLR via C#
(美)Jeffrey Richter / 周靖 / 清华大学出版社 / 2010-9 / 99.00元
本书针对CLR和.NET Framework 4.0进行深入、全面的探讨,并结合实例介绍了如何利用它们进行设计、开发和调试。全书5部分29章。第Ⅰ部分介绍CLR基础,第Ⅱ部分解释如何设计类型,第Ⅲ部分介绍基本类型,第Ⅳ部分以实用特性为主题,第Ⅴ部分花大量篇幅重点介绍线程处理。 通过本书的阅读,读者可以掌握CLR和.NET Framework的精髓,轻松、高效地创建高性能应用程序。一起来看看 《CLR via C#》 这本书的介绍吧!