双手.合十 2022-08-25 15:43
浏览 9
已结题

webuploader分片文件存在还会重新上传怎么回事?

前端




 <head>
    <link rel="stylesheet" type="text/css"
          href="../static/webuploader-0.1.5/webuploader.css">
    <link rel="stylesheet" type="text/css"
          href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/css/bootstrap.min.css">
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/2.2.2/jquery.min.js"></script>
    <script src="../static/webuploader-0.1.5/webuploader.min.js"></script>
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/bootstrap/5.1.3/js/bootstrap.min.js"></script>
</head>
<div id="uploader" class="container">
    
    <div id="thelist" class="row">
        <div class="panel panel-primary">
            <div class="panel-heading">文件上传</div>
            <table class="table table-striped table-bordered" id="uploadTable">
                <thead>
                <tr>
                    <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>
            </div>
        </div>
    </div>
</div>


<script type="text/javascript">
    var fileMd5;
    var fileSuffix;
    var $list = $("#thelist table>tbody");
    var state = 'pending';//初始按钮状态
    var $btn = $("#btn");
    var count = 0;
    //监听分块上传过程中的三个时间点
    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, 1024)
                .progress(function (percentage) {
                    $('#' + file.id).find("td.state").text("正在读取文件信息...");
                }).then(function (val) {
                fileMd5 = val;
                $('#' + file.id).find("td.state").text("成功获取文件信息...");
                //获取文件信息后进入下一步
                    deferred.resolve();
            });
            return deferred.promise();
        },

        //时间点2:如果有分块上传,则每个分块上传之前调用此函数
        beforeSend: function (block) {
            var deferred = WebUploader.Deferred();

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

        //时间点3:所有分块上传成功后调用此函数
        afterSendFile: function (file) {
            //如果分块上传成功,则通知后台合并分块
            $.ajax({
                type: "POST",
                url: "/mergeChunks/",
                data: {
                    fileId: file.id,
                    fileMd5: fileMd5,
                    fileSuffix: fileSuffix,
                    fileName: file.name,
                },
                success: function (response) {
                    console.log(response.fileName + " 上传成功")
                    $('#del' + file.id).hide();
                }
            });
        }
    });

    var uploader = WebUploader.create({
            // swf文件路径
            swf: '../static/webuploader-0.1.5/Uploader.swf',
            // 文件接收服务端。
            server: "/upload/",
            // 选择文件的按钮。可选。

            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: {
                id: '#picker',
                multiple: true
            },
            // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
            resize: true,
            auto: false,
            //开启分片上传
            chunked: true,
            chunkSize: 10 * 1024 * 1024,

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

    // 当有文件被添加进队列的时候
    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(
            '.id + '" class="item" flag=0>' +
            '' + count + '' +
            '' + file.name + '' +
            '' + fileSizeStr + '' +
            '等待上传...' +
            '' +
            '<button name="upload" id="del'</span> + file<span class="hljs-built_in">.id + '" class="btn btn-warning">开始</button><button name="delete" class="btn btn-error">删除</button>');
    });

    // 文件上传过程中创建进度条实时显示。
    uploader.on('uploadProgress', function (file, percentage) {
        $('#' + file.id).find('td.percentage').text(
            '上传中 ' + Math.round(percentage * 100) + '%');
    });

    uploader.on('uploadSuccess', function (file) {
        $('#' + file.id).find('td.state').text('已上传');
    });

    uploader.on('uploadError', function (file) {
        $('#' + file.id).find('td.state').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));
    });
</script>



FILE_PATH='files/'
def upload(request):
    """
    前端上传的分片 保存到 指定的目录下
    :param request: 
    :return: 
    """
    if request.method == 'POST':
        md5 = request.POST.get("fileMd5")
        chunk_id = request.POST.get("chunk", "0")
        fileName = "%s-%s" % (md5, chunk_id)
        file = request.FILES.get("file")
        with open(FILE_PATH + fileName, 'wb') as f:
            for i in file.chunks():
                f.write(i)
        return JsonResponse({'upload_part': True})

def checkChunk(request):
    """
    检查上传分片是否重复,如果重复则不提交,否则提交
    :param request:
    :return:
    """
    if request.method == 'POST':
        chunkSize = request.POST.get("chunkSize")
        if chunkSize == '0':
            return JsonResponse({'ifExist': True})
        file_name = request.POST.get('fileMd5') +'-'+ request.POST.get('chunk')
        # print(file_name)
        # print(get_deep_data())
        if file_name not in get_deep_data():
            return JsonResponse({'ifExist': False})
        return JsonResponse({'ifExist': True})
        
def get_deep_data(path=FILE_PATH):
    """
    判断一个文件是否在一个目录下
    :param path:
    :return:
    """
    result = []
    data = os.listdir(path)
    for i in data:
        if os.path.isdir(i):
            get_deep_data(i)
        else:
            result.append(i)
    return result

def mergeChunks(request):
    """
    将每次上传的分片合并成一个新文件,并删除分片数据
    :param request:
    :return:
    """
    if request.method == 'POST':
        chunk = 0
        id = request.POST.get("fileId")
        md5 = request.POST.get("fileMd5")
        fileName = request.POST.get("fileName")

        path = os.path.join(FILE_PATH, fileName)
        with open(path, 'wb') as fp:
            while True:
                try:
                    filename = FILE_PATH + '/{}-{}'.format(md5, chunk)
                    with open(filename, 'rb') as f:
                        fp.write(f.read())
                    os.remove(filename)
                except:
                    break
                chunk += 1

        return JsonResponse({'upload': True, 'fileName': fileName, 'fileId': id})

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 9月2日
    • 创建了问题 8月25日

    悬赏问题

    • ¥15 grbl为何无法移动到比复位坐标更小的坐标?
    • ¥60 怎样隐藏win7系统进程?
    • ¥15 CBF预处理数据归一化的时候报错了如下图
    • ¥15 qt 转 msvc 后 Opencv 始终打不开视频!
    • ¥15 yolo v5中labelimg的作用
    • ¥15 国赛c题2021,没有理解这一串代码的意思,这样报错该怎么解决(语言-matlab)
    • ¥15 一、执行完中断程序后如何继续运行,二、中断结束后如何跳过中断触发前的点位(LOW点不要继续运行,可以运行UP点)(关键词-程序运行)
    • ¥15 if为什么跳过if 直接执行else 中文
    • ¥200 解决登录微信老版本限制封号问题
    • ¥15 mysql中时间处理问题