django+python大文件上传

发布时间:2019-09-13 09:31:12编辑:auto阅读(1715)

    大文件上传服务
    一、前端
    [webuploader](http://fex.baidu.com/webuploader/ ''webuploader'')
    二、后端
    django 2.0.0
    这里只贴出核心的代码:
    前端的:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!--引入CSS-->
    <link rel="stylesheet" type="text/css" href="https://cdn.staticfile.org/webuploader/0.1.1/webuploader.css">
    <link rel="stylesheet" type="text/css" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.3/css/bootstrap.css">
    
    <!--引入JS-->
    <script type="text/javascript" src="https://cdn.staticfile.org/jquery/3.3.1/jquery.js"></script>
    <script type="text/javascript" src="https://cdn.staticfile.org/webuploader/0.1.1/webuploader.js"></script>
    <script type="text/javascript" src="https://cdn.staticfile.org/twitter-bootstrap/4.1.3/js/bootstrap.js"></script>
    </head>
    <body>
    <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 class="progress">         <!-- 进度条 -->
                <div class="progress-bar progress-bar-striped active" role="progressbar" style="width:0%;"></div>
            </div>
    </div>
     <script type="text/javascript">
        $(document).ready(function() {
            var task_id = WebUploader.Base.guid();        //产生task_id
            var uploader = WebUploader.create({           //创建上传控件
                swf: 'https://cdn.staticfile.org/webuploader/0.1.1/Uploader.swf', //swf位置,这个可能与flash有关
                server: '/resource/files/upload/',                 //接收每一个分片的服务器地址
                pick: '#picker',                          //填上传按钮的id选择器值
                auto: true,                               //选择文件后,是否自动上传
                chunked: true,                            //是否分片
                chunkSize: 10 * 1024 * 1024,              //每个分片的大小,这里为10M
                chunkRetry: 3,                            //某分片若上传失败,重试次数
                threads: 1,                               //线程数量,考虑到服务器,这里就选了1
                duplicate: true,                          //分片是否自动去重
                formData: {                               //每次上传分片,一起携带的数据
                    task_id: task_id,
                },
            });
    
            uploader.on('startUpload', function() {       //开始上传时,调用该方法
                $('.progress-bar').css('width', '0%');
                $('.progress-bar').text('0%');
            });
    
            uploader.on('uploadProgress', function(file, percentage) { //一个分片上传成功后,调用该方法
                $('.progress-bar').css('width', percentage * 100 - 1 + '%');
                $('.progress-bar').text(Math.floor(percentage * 100 - 1) + '%');
            });
    
            uploader.on('uploadSuccess', function(file) { //整个文件的所有分片都上传成功,调用该方法
                //上传的信息(文件唯一标识符,文件名)
                var data = {'task_id': task_id, 'filename': file.source['name'] };
                $.get('/resource/upload/complete/', data);          //ajax携带data向该url发请求
                $('.progress-bar').css('width', '100%');
                $('.progress-bar').text('上传完成');
            });
    
            uploader.on('uploadError', function(file) {   //上传过程中发生异常,调用该方法
                $('.progress-bar').css('width', '100%');
                $('.progress-bar').text('上传失败');
            });
    
            uploader.on('uploadComplete', function(file) {//上传结束,无论文件最终是否上传成功,该方法都会被调用
                $('.progress-bar').removeClass('active progress-bar-striped');
            });
    
        });
        </script>
    
    </body>
    </html>

    后端的:
    路由

        path('files/upload/', views.fileupload,name='图片分片上传'),
        path('upload/complete/', views.fileMerge,name='上传成功合并'),

    视图:

    @csrf_exempt
    def fileupload(request):
        if request.method == 'POST':
            upload_file = request.FILES.get('file')
            task = request.POST.get('task_id')  # 获取文件唯一标识符
            chunk = request.POST.get('chunk', 0)  # 获取该分片在所有分片中的序号
            filename = '%s%s' % (task, chunk)  # 构成该分片唯一标识符
            print("filename=",filename)
            default_storage.save('./upload/%s' % filename,ContentFile(upload_file.read()))  # 保存分片到本地
        return render_to_response('upload.html',locals())
    
    @csrf_exempt
    def fileMerge(request):
        print(request.GET)
        task = request.GET.get('task_id')
        ext = request.GET.get('filename', '')
        upload_type = request.GET.get('type')
        if len(ext) == 0 and upload_type:
            ext = upload_type.split('/')[1]
        ext = '' if len(ext) == 0 else '.%s' % ext  # 构建文件后缀名
        chunk = 0
        with open('./upload/%s%s' % (task, ext), 'wb') as target_file:  # 创建新文件
            while True:
                try:
                    filename = './upload/%s%d' % (task, chunk)
                    source_file = open(filename, 'rb')  # 按序打开每个分片
                    target_file.write(source_file.read())  # 读取分片内容写入新文件
                    source_file.close()
                except IOError:
                    break
                chunk += 1
                os.remove(filename)  # 删除该分片,节约空间
        return render_to_response('upload.html',locals())

    效果图:
    django+python大文件上传

关键字

上一篇: Python 代码规范

下一篇: Python的几种实现