基於php+webuploader的大文件分片上傳,支持斷點續傳,帶進度條

来源:https://www.cnblogs.com/zxf100/archive/2023/02/03/17089739.html
-Advertisement-
Play Games

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


基於php+webuploader的大文件分片上傳,帶進度條,支持斷點續傳(刷新、關閉頁面、重新上傳、網路中斷等情況)。文件上傳前先檢測該文件是否已上傳,如果已上傳提示“文件已存在”,如果未上傳則直接上傳。視頻上傳時會根據設定的參數(分片大小、分片數量)進行上傳,上傳過程中會在目標文件夾中生成一個臨時文件夾,用於存儲臨時分片,等所有分片上傳完畢後,會根據序號重新組合成一個完整的視頻,臨時文件被刪除。

如果文件上傳至七牛雲,可參看基於php大文件分片上傳至七牛雲,帶進度條

首先下載webuploader

效果圖:

 

 臨時文件,用於存儲分片

 

 

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']=	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 前面我們已經學習了Python的基礎語法,瞭解了Python的分支結構,也就是選擇結構、迴圈結構以及函數這些具體的框架,還學習了列表、元組、字典、字元串這些Python中特有的數據結構,還用這些語法完成了一個簡單的名片管理系統。下麵我就將介紹一下Python的一些進階語法規則,為後面更複雜的編 ...
  • Map 介面與 Collection 併列存在的,用於保存具有映射關係的數據:key-value 被稱為 鍵值對 。Java集合可分為 Collection 和 Map 兩種體系。Map 中的 key 和 value 都可以是任何引用類型的數據。Map 中的 key 用 Set 集合存儲的,不允許... ...
  • 鋼鐵知識庫,一個學習python爬蟲、數據分析的知識庫。人生苦短,快用python。 使用pycharm創建python文件時候,有時候需要自動生成想要的文件頭,如何生成呢? 只需要以下幾步: 在file->settings中搜索temp,找到file and code templates->pyt ...
  • Java集合框架 每博一文案 《殺死一隻知更鳥》中有這樣一段話:“你永遠不可能真正地瞭解一個人,除非你穿上他的鞋子走來走去,站在他的角度思考問題。 可真當你走過他的路時,你連路過都覺得難過。” 世上沒有真正的感同身受,也永遠不會有一模一樣的境遇。 很多時候,你以為看到了全貌,但其實只有冰山一角。永遠 ...
  • 最大公約數演算法不是很無聊,計算最大公約數是數學中一個重要的概念,可以用於判斷兩個數是否互質、求分數的約分等,在很多領域都有廣泛的應用。具體如下: 判斷兩個數是否互質:兩個數的最大公約數為1,說明這兩個數是互質的。 求分數的約分:將分子和分母的最大公約數約分掉,使得分數的值不變。 求同餘方程的最小正整 ...
  • 聲明 本文章中所有內容僅供學習交流,抓包內容、敏感網址、數據介面均已做脫敏處理,嚴禁用於商業用途和非法用途,否則由此產生的一切後果均與作者無關,若有侵權,請聯繫我立即刪除! 本文章未經許可禁止轉載,禁止任何修改後二次傳播,擅自使用本文講解的技術而導致的任何意外,作者均不負責,若有侵權,請在公眾號【K ...
  • BP(Back Propagation)演算法是一種常用的神經網路訓練演算法,主要用於識別分類和預測。常用於圖像識別、語音識別、文本分類等場景。它的原理是通過對誤差進行反向傳播來更新網路的參數,使得模型的誤差最小。BP演算法最早於1986年由Rumelhart等人提出。BP演算法適用於處理非線性問題,並且不 ...
  • 基於php大文件分片上傳至七牛雲,使用的是七牛雲js-sdk V2版本,引入js文件,配置簡單,可以暫停,暫停後支持斷點續傳(刷新、關閉頁面、重新上傳、網路中斷等情況),可以配置分片大小和分片數量,官方文檔https://developer.qiniu.com/kodo/6889/javascrip ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...