使用webuploader實現大文件斷點續傳(前端部分)


  要使用WebUploader實現大文件的斷點續傳需要分成幾個步驟去實現:

    1.在文件上傳之前把文件的標識(一般是文件的md5值)傳到服務器進行驗證,如果文件已經上傳過了,就不執行上傳操作了。

    2.每個分塊上傳之前判斷該分塊是否已經上傳過了,如果當前分塊已經上傳過了,就跳過,不再上傳了。

    3.所有分塊上傳完之后告訴服務器端,把分塊重新合並為一個文件。

 

  要用webuploader實現以上的的幾個步驟,需要用到自定義鈎子函數,具體可以看webuploader的文檔中的HOOk(鈎子)。

文檔中只介紹了webuploader的幾個比較重要的鈎子,如下圖所示:

  

  其中我在項目當中只用到了before-send-file和before-send這兩個鈎子,有些文章也會用到第三個鈎子,用於分塊上傳完成后通知后台對分塊進行合並,而我是在uploadsuccess的事件當中進行這步操作的。

  也許會有人會想,uploadStart和uploadBeforeSend相當於before-send-file和before-send,那為什么不用呢?我認為有兩點原因,

  第一:因為按以上所說的實現思路去做的話就要用ajax訪問后台的接口,而ajax是一個異步的操作,需要用到promise對象去控制回調,webuploader推薦我們在鈎子函數當中進行異步的操作並通過使用promise對象對回調進行控制。

  第二:根據實現思路的第二步,需要拿到分塊的信息才能判斷是否該分塊是否已經上傳過,而uploadBeforSend這個事件的三個參數分別是obj(相當於file),data(傳給后台的參數,相當於formdata,可用於設置參數把文件的md5傳給后台用於判斷分塊屬於哪個文件),header(用於設置請求頭),這三個參數都沒有一個與分塊有關的,所以更沒法用了。

  說了這么多,現在該說重點了。

  要分塊上傳,首先得在webuploader初始化的時候設置chunked:true,chunkSize:10*1024*1024

  接着就是編寫鈎子函數了,在beforeSendFile當中先創建一個Deferred對象,然后用ajax把文件的md5值傳給后台檢驗文件是否上傳過,如果已經上傳過了,就執行deferred.reject(),這時會觸發uploadError事件,如果之前上傳中斷了,則把中斷的位置獲取回來,這里我是直接讓后端返回上傳了多少塊,如果沒有上傳過或者上傳中斷了就執行deferred.resolve(),最后return deferred.promise();

  編寫before-send鈎子函數,該函數中有一個chunk的對象,該對象當中有一個chunk的屬性去標識當前是第幾個分塊,我用這個屬性值與之前上傳中斷的位置做比較(如果有中斷的話),如果小於已上傳的分塊數,則執行deferred.reject(),那么就會跳過該分塊的上傳了,否則就執行deferred.resolve()然分塊執行上傳的操作,然后就會進入uploadBeforSend事件了。

  最后,在uploadSuccess的事件當中調用接口告訴服務器,讓服務器把分塊進行合並,然后文件的上傳就完成了。

  

 代碼實現:

<script>
    
    var GUID = WebUploader.Base.guid();//一個GUID
    var chunkObj = {};	//用來記錄文件的狀態、上傳中斷的位置
    $(function () {
        var $ = jQuery;
        var $list = $('#thelist');
        WebUploader.Uploader.register({
            "before-send-file":"beforeSendFile",
            "before-send": "beforeSend"
        }, {
            "beforeSendFile": function (file) {
                var deferred = WebUploader.Deferred();
                $.ajax({
                    url: "/PublicInfoManage/ResourceFile/isCheckFiles",
                    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;
                        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;
                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: applicationPath + '../Content/scripts/plugins/webuploader/Uploader.swf',

            // 文件接收服務端。
            server: applicationPath + 'PublicInfoManage/ResourceFile/Upload',

            // 選擇文件的按鈕。可選。
            // 內部根據當前運行是創建,可能是input元素,也可能是flash.
            pick: '#picker',

            chunked: true,//開始分片上傳
            chunkSize: 20 * 1024 * 1024,//每一片的大小
            //threads: 3,
            formData: {
                seq: seq,
                //fileMd5: "0a663bd7f40f52cb77584ab43c3afd51",
                guid: GUID //自定義參數,待會兒解釋
            },

            // 不壓縮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"><img src="/Content/images/filetype/' + file.ext + '.png" /></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.fileMd5 = $.md5(file.name + file.size + file.ext);
        })
        // 文件上傳成功,給item添加成功class, 用樣式標記上傳成功。
        uploader.on('uploadSuccess', function (file, response) {
            $('#' + file.id).find('p.state').text('已上傳');
            $.post('../../PublicInfoManage/ResourceFile/Merge', { seq: seq, fileMd5: $.md5(file.name + file.size + file.ext), folderId: folderId, guid: GUID, fileName: file.name }, function (data) {
                $('#' + file.id).find('.progress').fadeOut();
                data = JSON.parse(data);
                if (data.message == "上傳成功") {
                    $("#uploader .state").html("上傳成功");
                    $.currentIframe().$("#gridTable").trigger("reloadGrid");
                } else {
                    $("#uploader .state").html("上傳出錯");
                    return false;
                }

            });
        });

        // 文件上傳失敗,顯示上傳出錯。
        uploader.on('uploadError', function (file) {
            $('#' + file.id).find('p.state').text('上傳出錯');
        });

        // 完成上傳完了,成功或者失敗,先刪除進度條。
        uploader.on('uploadComplete', function (file) {
            //$('#' + file.id).find('.progress').fadeOut();
        });

        //所有文件上傳完畢
        uploader.on("uploadFinished", function () {
            //提交表單

        });
        //開始上傳
        $("#ctlBtn").click(function () {
            uploader.upload();

        });

        //給上傳按鈕綁定文件上傳方法
        //$(document).on('click', '.btn_upload', function () {
        //    var fileId = $(this).closest(".item").attr("id");
        //    uploader.upload();
        //})

    });
</script>

  

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM