解决WebUploader断点续传md5混乱导致的文件合并错误问题

Posted Jason_WangYing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决WebUploader断点续传md5混乱导致的文件合并错误问题相关的知识,希望对你有一定的参考价值。

前一篇文章我们介绍了WebUploader集成到Django上的应用,在部署时发现错误了。

调试了半天发现是我用的变量有问题,

WebUploader.Uploader.register({
          "before-send-file" : "beforeSendFile",
          "before-send" : "beforeSend",
          "after-send-file" : "afterSendFile",
      },

这里的事件不是完全走完之后再走下一个的,是一个文件before-send走完,下一个文件就接着走,不会等"after-send-file结束才进行下一个文件传输,这样的话,我原来用的变量的fileMD5就好造成before-send传输文件3,但是after-send-file本来传输文件2,但是现在传的fileMD5是文件3的,下面是优化的html代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>webuploader上传</title>
    <link rel="stylesheet" type="text/css"
          href="https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.1/webuploader.css">
    <link rel="stylesheet" type="text/css"
          href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="/static/webuploader/webuploader.css">
    <link rel="stylesheet" type="text/css" href="/static/bootstrap/css/bootstrap.min.css">
    <script src="/static/jquery-2.2.3.min.js"></script>
    <script src="/static/webuploader/webuploader.min.js"></script>
    <script type="text/javascript" src="/static/hashmap.js"></script>
    <style type="text/css">
        #picker {
            display: inline-block;
            line-height: 1.428571429;
            vertical-align: middle;
            margin: 0 12px 0 0;
        }
    </style>
</head>
<body>
<div id="uploader" class="container">
    <!--用来存放文件信息-->
    <div id="thelist" class="row">
        <div class="panel panel-primary">
            <div class="panel-heading">webuploader文件上传</div>
            <table class="table table-striped table-bordered" id="uploadTable">
                <thead>
                <tr>
                    <th>序号</th>
                    <th>文件名称</th>
                    <th>备注</th>
                    <th>文件大小</th>
                    <th>上传状态</th>
                    <th>上传进度</th>
                    <th style="width:15%;">操作</th>
                </tr>
                </thead>
                <tbody></tbody>
            </table>
            <div class="panel-footer">
                <div id="picker">选择文件</div>
                <button id="btn" class="btn btn-default">开始上传</button>
                <p id='message'>
            </div>
            <div class="progress">         <!-- 进度条 -->
                <div class="progress-bar progress-bar-striped active" role="progressbar" style="width:0%;"></div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    var $list = $("#thelist table>tbody");
    var state = 'pending';//初始按钮状态
    var $btn = $("#btn");
    var count = 0;
    var map = new HashMap();

    //监听分块上传过程中的三个时间点
    WebUploader.Uploader.register({
        "before-send-file": "beforeSendFile",
        "before-send": "beforeSend",
        "after-send-file": "afterSendFile",
    }, {
        //时间点1:所有分块进行上传之前调用此函数
        beforeSendFile: function (file) {
            var deferred = WebUploader.Deferred();
            //1、计算文件的唯一标记,用于断点续传
            // (new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024)
            (new WebUploader.Uploader()).md5File(file, 0, 1024)
                .progress(function (percentage) {
                    $('#' + file.id).find("td.state").text("正在读取文件信息...");
                }).then(function (val) {
                file.md5 = val;
                $('#' + file.id).find("td.state").text("成功获取文件信息...");
                //获取文件信息后进入下一步
                deferred.resolve();
            });
            return deferred.promise();
        },
        //时间点2:如果有分块上传,则每个分块上传之前调用此函数
        beforeSend: function (block) {
            var deferred = WebUploader.Deferred();

            $.ajax({
                type: "POST",
                url: "{% url 'checkChunk'%}",
                data: {
                    //文件唯一标记
                    fileMd5: block.file.md5,
                    //当前分块下标
                    chunk: block.chunk,
                    //当前分块大小
                    chunkSize: block.end - block.start
                },
                dataType: "json",
                success: function (response) {
                    if (response.ifExist) {
                        //分块存在,跳过
                        deferred.reject();
                    } else {
                        //分块不存在或不完整,重新发送该分块内容
                        deferred.resolve();
                    }
                }
            });

            this.owner.options.formData.fileMd5 = block.file.md5;
            deferred.resolve();
            return deferred.promise();
        },
        //时间点3:所有分块上传成功后调用此函数
        afterSendFile: function (file) {
            //如果分块上传成功,则通知后台合并分块
            var beizhu_value = document.getElementById('beizhu' + file.id).value
            $.ajax({
                type: "POST",
                url: "{% url 'mergeChunks'%}",
                data: {
                    fileId: file.id,
                    fileMd5: file.md5,
                    fileSuffix: file.ext,
                    fileName: file.name,
                    beizhu: beizhu_value,
                },
                success: function (response) {
                    console.log(response.fileName + " 上传成功")
                    $('#del' + file.id).hide();
                }
            });
        }
    });

    var uploader = WebUploader
        .create({
            // swf文件路径
            swf: 'https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.1/Uploader.swf',
            // 文件接收服务端。
            server: "{% url 'upload' %}",
            // 选择文件的按钮。可选。
            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: {
                id: '#picker',//这个id是你要点击上传文件的id
                multiple: true
            },
            // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
            resize: true,
            auto: false,
            //开启分片上传
            chunked: true,
            chunkSize: 10 * 1024 * 1024,

            accept: {
                extensions: "txt,csv,jpg,jpeg,bmp,png,zip,rar,war,pdf,cebx,doc,docx,ppt,pptx,xls,xlsx,iso,flv,mp4,exe",
                mimeTypes: '.txt,.csv,.jpg,.jpeg,.bmp,.png,.zip,.rar,.war,.pdf,.cebx,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.iso,.flv,.mp4,.exe'
            }

        });

    // 当有文件被添加进队列的时候
    uploader.on('fileQueued', function (file) {
        //保存文件扩展名
        fileSuffix = file.ext;
        fileName = file.source['name'];
        var fileSize = file.size;
        var fileSizeStr = "";
        fileSizeStr = WebUploader.Base.formatSize(fileSize);
        count++;
        $list.append(
            '<tr id="' + file.id + '" class="item" flag=0>' +
            '<td class="index">' + count + '</td>' +
            '<td class="info">' + file.name + '</td>' +
            '<td class="beizhu"><input id="beizhu' + file.id + '" ' + 'type="text">' + '</td>' +
            '<td class="size">' + fileSizeStr + '</td>' +
            '<td class="state">等待上传...</td>' +
            '<td class="percentage"></td>' +
            '<td class="operate"><button name="upload" id="del' + file.id + '" class="btn btn-warning">开始</button><button name="delete" class="btn btn-error">删除</button></td></tr>');
        map.put(file.id + "", file);
        $('.progress-bar').css('width', '0%');
        $('.progress-bar').text('0%');
        $('#message').text(file.name)
    });

    // 文件上传过程中创建进度条实时显示。
    uploader.on('uploadProgress', function (file, percentage) {//一个分片上传成功后,调用该方法
        $('#' + file.id).find('td.percentage').text(
            '上传中 ' + Math.round(percentage * 100) + '%');
        $('.progress-bar').css('width', percentage * 100 - 1 + '%');
        $('.progress-bar').text(Math.floor(percentage * 100 - 1) + '%');
    });

    uploader.on('uploadSuccess', function (file) {//整个文件的所有分片都上传成功,调用该方法
        $('#' + file.id).find('td.state').text('已上传');
        $('.progress-bar').css('width', '100%');
        $('.progress-bar').text('上传完成');
    });

    uploader.on('uploadError', function (file) {//上传过程中发生异常,调用该方法
        $('#' + file.id).find('td.state').text('上传出错');
        $('.progress-bar').css('width', '100%');
        $('.progress-bar').text('上传失败');
    });

    uploader.on('uploadComplete', function (file) {//上传结束,无论文件最终是否上传成功,该方法都会被调用
        uploader.removeFile(file);
    });


    uploader.on('all', function (type) {
        if (type === 'startUpload') {
            state = 'uploading';
        } else if (type === 'stopUpload') {
            state = 'paused';
        } else if (type === 'uploadFinished') {
            state = 'done';
        }

        if (state === 'uploading') {
            $btn.text('暂停上传');
        } else {
            $btn.text('开始上传');
        }
    });

    $btn.on('click', function () {
        if (state === 'uploading') {
            uploader.stop(true);
        } else {
            uploader.upload();
        }
    });

    $("body").on("click", "#uploadTable button[name='upload']", function () {
        flag = $(this).parents("tr.item").attr("flag") ^ 1;
        $(this).parents("tr.item").attr("flag", flag);
        var id = $(this).parents("tr.item").attr("id");
        if (flag == 1) {
            $(this).text("暂停");
            uploader.upload(uploader.getFile(id, true));

        } else {
            $(this).text("开始");
            uploader.stop(uploader.getFile(id, true));
        }
    });

    $("body").on("click", "#uploadTable button[name='delete']", function () {
        var id = $(this).parents("tr.item").attr("id");
        $(this).parents("tr.item").remove();
        uploader.removeFile(uploader.getFile(id, true));
        map.remove(id);
    });
</script>
</body>
</html>

以上是关于解决WebUploader断点续传md5混乱导致的文件合并错误问题的主要内容,如果未能解决你的问题,请参考以下文章

webuploader+web如何实现分片+断点续传

webuploader与django进行断点续传

jsp利用webuploader实现超大文件分片上传断点续传

webUploader实现大文件分片,断点续传

java使用WebUploader做大文件的分块和断点续传

webUploader大文件断点续传学习心得 多文件