基于php+webuploader的大文件分片上传,支持断点续传,带进度条
1.PHP 二维数组相关函数:二维数组指定key排序,二维数组转一维数组,两个二维数组取差集,对象转数组,判断元素是否在多维数组中2.PHP获取时间戳、获取天周月的起始时间、指定时间所在周、指定时间的各个周等相关函数3.PHP使用ZipArchive批量打包压缩文件并下载4.基于php大文件分片上传至七牛云,支持断点续传,,带进度条
5.基于php+webuploader的大文件分片上传,支持断点续传,带进度条
6.PHP PDF转图片7.PHP 通过两个日期计算年龄8.PHP使用pdfparser实现对PDF转换成本文9.php获取图片的主要颜色值RGB10.PHP实现无限级分类11.ThinkPHP5浏览器关闭,继续执行php脚本12.ThinkPHP5权限管理13.PHP+Redis实现排行榜14.PHP操作Redis常用命令15.Thinkphp5+Redis实现商品秒杀16.ThinkPHP5+Redis实现购物车17.用PHP实现SSO单点登录系统接入功能与分析18.PHP自动加载composer下载的类库19.Windows上composer安装20.ThinkPHP5分布式数据库读写分离21.THINKPHP5截取标题长度并加省略号22.ThinkPHP5+WebSocket+MySQL实现聊天室23.php+websocket 实现聊天室24.thinkphp实现用户注册时邮箱激活25.Thinkphp5+PHPMailer实现发送邮件26.thinkphp+jquery实现两级评论回复效果27.PHP开发API接口签名生成及验证28.php 使用 CURL 获取数据29.PHP正则表达式常用例子30.微信小程序+php 授权登陆,完整代码31.thinkphp5 + barcode 生成条形码32.PHP查询附近的人及其距离的实现方法33.thinkPHP+LayUI 懒加载实现34.php与阿里云短信接口接入35.php日期格式化方法详解36.php 根据URL下载远程图片、压缩包、pdf等文件到本地37.php+js实现极验,拖动滑块验证码验证表单38.php无限分类方法类39.php的多功能文件操作类40.计算地图上两点间的距离PHP类41.php的微信公众平台开发接口类42.身份证验证PHP类43.php使用fullcalendar日历插件44.php通过某个日期段的周几,获取选中周几对应的日期45.thinkphp 使用paginate分页搜索带参数46.php对二维数据排序47.php获取指定月份月初和月末的时间戳48.PHP批量导出数据为excel表格49.php实现同一时间内一个账户只允许在一个终端登陆50.ThinkPHP5+Layui实现图片上传加预览51.php+layui实现图片上传与预览52.PHP实现无限级分类53.PHP获取本周的每一天的时间54.php生成word,并下载55.PHP实现大转盘抽奖算法56.判断当前浏览器是不是微信浏览器57.ThinkPHP5下自己写日志58.Bootstrap+PHP实现多图上传59.ThinkPHP5事务回滚60.php获取本月、上月、上上月、今日、昨日、上周的起始时间61.ThinkPHP5自定义分页样式62.thinkphp5+qrcode生成二维码63.ThinkPHP_5对数据库的CURL操作64.PHP异常处理65.ThinkPHP实现登陆功能66.使用ThinkPHP实现分页功能67.使用ThinkPHP实现生成缩略图及显示68.使用ThinkPHP实现生成/校验验证码功能69.使用ThinkPHP实现附件上传70.ThinkPHP中create()方法自动验证表单信息71.PHP实现文件下载72.PHP实现批量删除(封装)73.php简单实现二级联动74.PHP中文件操作(2)-- 写文件75.PHP中文件操作(1)--打开/读取文件76.PHP中常用的魔术方法77.PHP生成缩略图(3)--封装类78.PHP生成缩略图(2)--等比缩略图79.PHP生成缩略图(1)--简单缩略图80.调用天气预报接口81.使用JSON实现分页82.使用AJAX实现分页83.PHP中NOTICE错误常见解决方法84.PHP解决中文乱码85.PHP中类和对象的相关函数86.PHP 绘制验证码87.PHP文件上传,下载,Sql工具类!88.PHP中Session的使用89.PHP中Cookie的使用---添加/更新/删除/获取Cookie 及 自动填写该用户的用户名和密码和判断是否第一次登陆90.PHP 类文件的自动加载机制 __autoload()基于php+webuploader的大文件分片上传,带进度条,支持断点续传(刷新、关闭页面、重新上传、网络中断等情况)。文件上传前先检测该文件是否已上传,如果已上传提示“文件已存在”,如果未上传则直接上传。视频上传时会根据设定的参数(分片大小、分片数量)进行上传,上传过程中会在目标文件夹中生成一个临时文件夹,用于存储临时分片,等所有分片上传完毕后,会根据序号重新组合成一个完整的视频,临时文件被删除。
如果文件上传至七牛云,可参看基于php大文件分片上传至七牛云,带进度条
效果图:
临时文件,用于存储分片
html代码
<title>webuploader分片上传</title> <meta charset="utf8"> <!--引入CSS--> <link rel="stylesheet" type="text/css" href="/static/webupload/webuploader.css"> <script type="text/javascript" src="/static/index/js/jquery.js"></script> <script type="text/javascript" src="/static/index/js/jquery.md5.js"></script> <!--引入JS--> <script type="text/javascript" src="/static/webupload/webuploader.js"></script> <div id="uploader" class="wu-example"> <!--用来存放文件信息--> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="picker">选择文件</div> <button id="ctlBtn" class="btn btn-default">开始上传</button> </div> </div> <style> .progress{ height: 20px; width: 300px; background: #ccc; } .progress-bar{ height: 20px; background: #0a3536;} </style> <script> var uploadswf = '/static/webupload/Uploader.swf'; var chunkSize = 2*1024*1024; var server_url='uploadVedio'; var GUID = WebUploader.Base.guid();//一个GUID var chunkObj = {}; //用来记录文件的状态、上传中断的位置 var seq=1; var msg=''; $(function () { var $ = jQuery; var $list = $('#thelist'); WebUploader.Uploader.register({ "before-send-file":"beforeSendFile", "before-send": "beforeSend" }, { "beforeSendFile": function (file) { //上传前校验文件是否已经上传过 var deferred = WebUploader.Deferred(); $.ajax({ type:"POST", //上传前校验文件上传到第几片 url: "checkFile", data: { seq: seq, fileMd5: $.md5(file.name + file.size + file.ext), fileName:file.name }, dataType: "json", success: function (data) { console.log(data); chunkObj = data; chunkObj.type = data.type; chunkObj.chunk == data.chunk; msg = data.msg; if(data.type==404){ deferred.reject(); $("#" + file.id).find(".state").text(data.msg); }else if (data.type == 0) { deferred.reject(); $("#" + file.id).find(".state").text("文件已上传"); } else if (data.type == 1) { if (data.chunk) { deferred.resolve(); } } else { deferred.resolve(); } }, error: function () { deferred.resolve(); } }) //deferred.resolve(); return deferred.promise(); }, "beforeSend": function (block) { var deferred = WebUploader.Deferred(); var curChunk = block.chunk; var totalChunk = block.chunks; console.log(chunkObj) if (chunkObj.type == "1") { if (curChunk < chunkObj.chunk) { deferred.reject(); } else { deferred.resolve(); } } else { deferred.resolve(); } return deferred.promise(); } }); var uploader = WebUploader.create({ // 选完文件后,是否自动上传。 auto: false, // swf文件路径 swf: uploadswf, // 文件接收服务端。 server: server_url, // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick: '#picker', chunked: true,//开始分片上传 chunkSize:1 * 1024 * 1024,//每一片的大小 threads: 1, formData: { }, // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传! resize: false }); // 当有文件被添加进队列的时候 uploader.on('fileQueued', function (file) { $list.append('<div id="' + file.id + '" class="item">' + '<div class="item-file"><div class="fileType-logo"></div>' + '<div class="fileMes"><h4 class="info">' + file.name + '</h4>' + '<p class="state">等待上传...</p>' + '</div></div></div>'); }); // 文件上传过程中创建进度条实时显示。 uploader.on('uploadProgress', function (file, percentage) { var $li = $('#' + file.id), $percent = $li.find('.progress .progress-bar'); // 避免重复创建 if (!$percent.length) { $percent = $('<div class="progress progress-striped active">' + '<div class="progress-bar" role="progressbar" style="width: 0%">' + '</div>' + '</div>').appendTo($li).find('.progress-bar'); } $li.find('p.state').text('上传中'); $percent.css('width', percentage * 100 + '%'); }); uploader.on("uploadBeforeSend", function (obj, data, headers) { var file = obj.cuted.file; data.test = 1; data.fileMd5 = $.md5(file.name + file.size + file.ext); }) // 文件上传成功,给item添加成功class, 用样式标记上传成功。 uploader.on('uploadSuccess', function (file, response) { if(response.status==299){ $('#' + file.id).find('p.state').text('文件已存在'); }else{ $('#' + file.id).find('p.state').text('已上传'); } }); // 文件上传失败,显示上传出错。 uploader.on('uploadError', function (file) { $('#' + file.id).find('p.state').text(msg); }); // 完成上传完了,成功或者失败,先删除进度条。 uploader.on('uploadComplete', function (file) { $('#' + file.id).find('.progress').fadeOut(); }); //所有文件上传完毕 uploader.on("uploadFinished", function () { //提交表单 }); //开始上传 $("#ctlBtn").click(function () { uploader.upload(); }); }); </script>
php请求后端
use app\index\controller\Upload;
public function uploadVedio() { $model =new Upload(); $res = $model->doUpload(); $model->ajaxReturn($res); }
封装上传类
<?php namespace app\index\controller; use think\Controller; /** * 大文件分片上传 */ class Upload extends Controller { private $filepath = 'uploads/'; //上传目录 private $blobNum; //第几个文件块 private $totalBlobNum; //文件块总数 private $fileName; //文件名 #允许上传的文件 private $allowExtension = ['mp4','avi','wmv']; #文件后缀 private $fileExtension =''; #当前块内容 private $nowFile = ''; #文件大小 private $totalSize = 0; #文件总大小只允许1G private $allowFileSize = 0; #文件md5 前端传过来的 用于创建临时文件夹 上传完后删除 private $fileMd5=''; public function __construct($savePath =''){ $postData = $_POST; #测试断点上传 if(isset($postData['test'])){ sleep(1); } if($savePath){ $this->filepath = $this->filepath.$savePath; } # #文件名称 # var_dump($postData); $postData['name'] =isset($postData['name'])?$postData['name']:''; $this->fileName =$postData['name']; if($this->isHaveFile()){ $this->ajaxReturn(['status'=>299,'msg'=>'文件已存在!']); } $this->fileMd5 =$postData['fileMd5']; #允许文件的大小 1G $this->allowFileSize =(1*1024*1024*1024); if((int)$postData['size']>$this->allowFileSize){ $this->ajaxReturn(['status'=>204,'msg'=>"文件大小超1G限制!"]); } #文件大小 $this->totalSize=$postData['size']; $postData['chunks']=isset($postData['chunks'])?(int)$postData['chunks']:1; $postData['chunk']=isset($postData['chunk'])?(int)$postData['chunk']:0; if(!(int)$postData['chunks']){ $this->ajaxReturn(['status'=>208,'msg'=>'chunks参数错误']); } #当前块 $this->blobNum =$postData['chunk']+1; #总共块 $this->totalBlobNum =$postData['chunks']; #获取后缀 $fileExtension =explode(".",basename( $this->fileName)); $this->fileExtension=array_pop($fileExtension); #检测后缀是否在允许范围 $this->checkFileExtension(); $this->nowFile = $_FILES['file']; if( $this->nowFile['error'] > 0) { $msg['status'] = 502; $msg['msg'] = "文件错误!"; $this->ajaxReturn($msg); } } public function doUpload(){ #临时文件移动到指定目录下 $res = $this->moveFile(); if($res['status']==999){ return $this->fileMerge(); }else{ return $res; } } #创建md5 文件名 public function createFileName(){ return $this->filepath.$this->fileName; } #检测文件是否重复 public function isHaveFile(){ if(file_exists($this->filepath.$this->fileName)){ return true; } return false; } #文件合并 public function fileMerge(){ if ($this->blobNum == $this->totalBlobNum) { $fileName = $this->createFileName(); @unlink($fileName); #删除旧文件 #文件合并 文件名以 $handle=fopen($fileName,"a+"); for($i=1; $i<= $this->totalBlobNum; $i++){ #当前分片数 $this->blobNum = $i; #吧每个块的文件追加到 上传的文件中 fwrite($handle,file_get_contents($this->createBlockFileName())); } fclose($handle); #删除分片 for($i=1; $i<= $this->totalBlobNum; $i++){ $this->blobNum = $i; @unlink($this->createBlockFileName()); } #删除临时目录 @rmdir($this->filepath.$this->fileMd5); if(filesize($fileName) == $this->totalSize){ $msg['status'] = 200; $msg['msg'] = '上传成功!'; $msg['size'] = $this->totalSize; $msg['filename'] = "http://".$_SERVER['HTTP_HOST']."/".$this->createFileName(); $msg['name'] = $this->fileName; }else{ $msg['status'] = 501; $msg['msg'] = '上传文件大小和总大小有误!'; @unlink($this->createFileName()); } return $msg; # $this->ajaxReturn($msg); } } #检测上传类型 public function checkFileExtension(){ if(!in_array(strtolower($this->fileExtension),$this->allowExtension)){ $this->ajaxReturn(['status'=>203,'msg'=>"文件类型不允许"]); } } #将临时文件移动到指定目录 public function moveFile(){ try{ #每个块的文件名 以文件名的MD5作为命名 $filename=$this->createBlockFileName(); #分片文件写入 $handle=fopen($filename,"w+"); fwrite($handle,file_get_contents($this->nowFile ['tmp_name'])); fclose($handle); #不是最后一块就返回当前信息 是最后一块往下执行合并操作 if($this->blobNum != $this->totalBlobNum) { $msg['status'] = 201; $msg['msg'] = "上传成功!"; $msg['blobNum'] = $this->blobNum; return $msg; #$this->ajaxReturn($msg); }else{ $msg['status'] = 999; $msg['msg'] = "上传成功!"; $msg['blobNum'] = $this->blobNum; return $msg; } }catch (Exception $e){ $msg['status'] = 501; $msg['error'] = $e->getMessage(); return $msg; #$this->ajaxReturn($msg); } } #创建分片文件名 public function createBlockFileName(){ $dirName = $this->filepath.$this->fileMd5."/"; if (!is_dir($dirName) ) { @mkdir($dirName, 0700); }; return $dirName.$this->blobNum.".part"; } #json格式放回处理 public function ajaxReturn($msg){ exit(json_encode($msg)); } }
——现在的努力,只为小时候吹过的牛逼! ——
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构