zoukankan      html  css  js  c++  java
  • webuploader与django进行断点续传

    webuploader与django进行断点续传

    • 需要实现的效果如下

    • 需要使用的 js

      • jquery.js
      • webuploader.hs
      • hashmap.js
    • 路由

      from django.urls import path
      from . import views
      urlpatterns = [
          path('index/',views.index),
          path('checkChunk/',views.checkChunk,name='checkChunk'),
          path('mergeChunks/',views.mergeChunks,name='mergeChunks'),
          path('upload/',views.upload,name='upload'),
      ]
      
    • 视图

      from django.shortcuts import render
      from django.http import JsonResponse
      import os
      
      def index(request):
          return render(request,'upload.html')
      
      # 检查上传分片是否重复,如果重复则不提交,否则提交
      def checkChunk(request):
          # post请求
          if request.method == 'POST':
              # 获得上传文件块的大小,如果为0,就告诉他不要上传了
              chunkSize = request.POST.get("chunkSize")
              if chunkSize == '0':
                  return JsonResponse({'ifExist': True})
              # 如果文件块大小不为0 ,那么就上传,需要拼接一个临时文件
              file_name = request.POST.get('fileMd5')+request.POST.get('chunk')
      
              # 如果说这个文件不在已经上传的目录,就可以上传,已经存在了就不需要上传。
              if file_name not in get_deep_data():
                  return JsonResponse({'ifExist': False})
              return JsonResponse({'ifExist': True})
      
      # 判断一个文件是否在一个目录下
      def get_deep_data(path='static/upload/'):
          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 upload(request):
          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('static/upload/'+fileName,'wb') as f:
                  for i in file.chunks():
                      f.write(i)
              return JsonResponse({'upload_part':True})
      
      
      # 将每次上传的分片合并成一个新文件
      def mergeChunks(request):
          if request.method == 'POST':
              # 获取需要给文件命名的名称
              fileName = request.POST.get("fileName")
              # 该图片上传使用的md5码值
              md5 = request.POST.get("fileMd5")
              id = request.POST.get("fileId")
              # 分片的序号
              chunk = 0
              # 完成的文件的地址为
              path = os.path.join('static','upload',fileName)
              with open(path,'wb') as fp:
                  while True:
                      try:
                          filename = 'static/upload/{}-{}'.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})
      
    • 前端

      <!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">
      <script src="/static/jquery-2.2.3.js"></script>
      <script src="/static/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 style="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;
      	  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) {
      						  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 : "{% url 'checkChunk'%}",
      				  data : {
      					  //文件唯一标记
      					  fileMd5 : fileMd5,
      					  //当前分块下标
      					  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 = fileMd5;
      			  deferred.resolve();
      			  return deferred.promise();
      		  },
      		  //时间点3:所有分块上传成功后调用此函数
      		  afterSendFile : function(file) {
      			  //如果分块上传成功,则通知后台合并分块
      			  $.ajax({
      				  type : "POST",
      				  url : "{% 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 : '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,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(
      				  '<tr id="' + file.id + '" class="item" flag=0>'+
      				  '<td class="index">' + count + '</td>'+
      				  '<td class="info">' + file.name + '</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);
      	  });
      
      	  // 文件上传过程中创建进度条实时显示。
      	  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));
      		  map.remove(id);
      	  });
        </script>
      </body>
      </html>
      
  • 相关阅读:
    蓝瓶的钙,好喝的钙——windows,我要蓝屏的
    gz文件最后四位检测
    中国Linux开源镜像站大全
    linux强制将数据写入磁盘,防止丢失内存的数据
    文件是否真的写入了磁盘?
    OpenStack之日志
    使用 Nmon 监控 Linux 的系统性能
    Android获取系统cpu信息,内存,版本,电量等信息
    Android——service重启
    Android——显示当前运行所有服务,判断服务是否运行
  • 原文地址:https://www.cnblogs.com/wuxiaoshi/p/12422915.html
Copyright © 2011-2022 走看看