基於php+webuploader的大文件分片上傳,帶進度條,支持斷點續傳(刷新、關閉頁面、重新上傳、網路中斷等情況)。文件上傳前先檢測該文件是否已上傳,如果已上傳提示“文件已存在”,如果未上傳則直接上傳。視頻上傳時會根據設定的參數(分片大小、分片數量)進行上傳,上傳過程中會在目標文件夾中生成一個臨 ...
基於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']=