zoukankan      html  css  js  c++  java
  • 07 第三方之文件上传

    上传文件

    一、自定义上传文件

     1 from flask import Flask,request
     2 from datetime import datetime
     3 import random
     4 app = Flask(__name__)
     5 
     6 @app.route('/upload',methods=['POST'])
     7 def upload():
     8   data = request.files.get('pic')
     9   # 随机图片名称
    10   pic=datetime.now().strftime('%Y%m%d%H%M%S')+str(random.randint(1000,9999))+'.png' 
    11   with open(pic,'wb') as f:
    12       f.write(data.read())
    13   return ''
    14 
    15 if __name__ == '__main__':
    16   app.run(debug=True)
    <form action='http://127.0.0.1:5000/upload' method='post' enctype="multipart/form-data">
      <input type='file' name='pic' />
      <input type='submit' value='submit' />
    </form>

    二、第三方上传文件 (webuploader)

     1 # server.py
     2 # 引入os模块,1,删除分片,节约物理空间,2,遍历上传的文件
     3 import os 
     4 from flask import Flask, request, Response, render_template,jsonify
     5 app = Flask(__name__)
     6 app.config.from_object('config')
     7 
     8 # 进入上传页面
     9 @app.route('/')
    10 def index():
    11   return render_template('uploads.html')
    12 
    13 # 检查上传分片是否重复,如果重复则不提交,否则提交
    14 @app.route('/checkChunk', methods=['POST'])
    15 def checkChunk():
    16   chunkSize = request.form.get('chunkSize') # 待上传文件的大小
    17   if chunkSize == '0':
    18       return jsonify({'ifExist': True}) # 不要上传
    19   file_name = request.form.get('fileMd5')+ request.form.get('chunk')
    20   if file_name not in get_deep_catalog():
    21       return jsonify({'ifExist': False})
    22   return jsonify({'ifExist':True})
    23 
    24 # 定义一个获取当前路径下的所有文件,应该放在公共函数库中
    25 def get_deep_catalog(path='./upload'):
    26   result = []
    27   list_catalog = os.listdir(path)
    28   for i in list_catalog:
    29       if os.path.isdir(i) == True:
    30           get_deep_catalog(i)
    31       else:
    32           result.append(i)
    33   return result
    34 
    35 # 将每次上传的分片合并成一个新文件
    36 @app.route('/mergeChunks', methods=['POST'])
    37 def mergeChunks():
    38   fileName=request.form.get('fileName') # 上传的文件名
    39   md5=request.form.get('fileMd5')
    40   chunk = 0  # 分片序号
    41   with open(u'./upload/{}'.format(fileName), 'wb') as target_file:  # 创建新文件
    42       while True:
    43           try:
    44               filename = './upload/{}-{}'.format(md5, chunk)
    45               source_file = open(filename, 'rb')  # 按序打开每个分片
    46               target_file.write(source_file.read())  # 读取分片内容写入新文件
    47               source_file.close()
    48           except Exception as e:
    49               break
    50           chunk += 1
    51           os.remove(filename)  # 删除该分片,节约空间
    52   return jsonify({'upload':True,'fileName':fileName})
    53 
    54 
    55 # 前端上传的分片 保存到 指定的目录下  ./upload
    56 @app.route('/upload', methods=['POST'])
    57 def upload():  # 接收前端上传的一个分片
    58   md5=request.form.get('fileMd5')
    59   chunk_id=request.form.get('chunk',0,type=int)
    60   filename = '{}-{}'.format(md5,chunk_id)
    61   upload_file = request.files['file']
    62   upload_file.save('./upload/{}'.format(filename))
    63   return jsonify({'upload_part':True})
    64 
    65 
    66 # 遍历 upload下的上传文件
    67 @app.route('/file/list', methods=['GET'])
    68 def file_list():
    69   files = os.listdir('./upload/')  # 获取文件目录
    70   return render_template('list.html', files=files)
    71 
    72 # 文件下载
    73 @app.route('/file/download/<filename>', methods=['GET'])
    74 def file_download(filename):
    75   def send_chunk():  # 流式读取
    76       store_path = './upload/%s' % filename
    77       with open(store_path, 'rb') as target_file:
    78           while True:
    79               chunk = target_file.read(20 * 1024 * 1024)
    80               if not chunk:
    81                   break
    82               yield chunk
    83   # application/octet-stream  是二进制文件的数据流或者字节数组
    84   return Response(send_chunk(), content_type='application/octet-stream')
    85 
    86 if __name__ == '__main__':
    87   app.run(debug=True)
      1 <!--
      2     上传页面   uploads.html
      3     extensions : 上传数据类型 例如 mp4
      4     mimeTypes  : 媒体资源类型,如 .mp4
      5 -->
      6 <!DOCTYPE html>
      7 <html>
      8 <head>
      9 <meta charset="UTF-8">
     10 <title>webuploader上传</title>
     11 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.1/webuploader.css">
     12 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
     13 <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
     14 <script src="/static/js/webuploader.min.js"></script>
     15 <script type="text/javascript" src="/static/js/hashmap.js"></script>
     16 <style type="text/css">
     17 #picker {
     18   display: inline-block;
     19   line-height: 1.428571429;
     20   vertical-align: middle;
     21   margin: 0 12px 0 0;
     22 }
     23 </style>
     24 </head>
     25 <body>
     26   <div id="uploader" class="container">
     27       <!--用来存放文件信息-->
     28       <div id="thelist" class="row">
     29           <div class="panel panel-primary">
     30               <div class="panel-heading">webuploader文件上传</div>
     31               <table class="table table-striped table-bordered" id="uploadTable">
     32                   <thead>
     33                       <tr>
     34                           <th>序号</th>
     35                           <th>文件名称</th>
     36                           <th>文件大小</th>
     37                           <th>上传状态</th>
     38                           <th>上传进度</th>
     39                           <th>操作</th>
     40                       </tr>
     41                   </thead>
     42                   <tbody></tbody>
     43               </table>
     44               <div class="panel-footer">
     45                   <div id="picker">选择文件</div>
     46                   <button id="btn" class="btn btn-default">开始上传</button>
     47               </div>
     48           </div>
     49       </div>
     50   </div>
     51   <script type="text/javascript">
     52       var fileMd5;
     53       var fileSuffix;
     54       var $list=$("#thelist table>tbody");
     55       var state = 'pending';//初始按钮状态
     56       var $btn=$("#btn");
     57       var count=0;
     58       var map=new HashMap();
     59       //监听分块上传过程中的三个时间点
     60       WebUploader.Uploader.register({
     61           "before-send-file" : "beforeSendFile",
     62           "before-send" : "beforeSend",
     63           "after-send-file" : "afterSendFile",
     64       }, {
     65           //时间点1:所有分块进行上传之前调用此函数
     66           beforeSendFile : function(file) {
     67               var deferred = WebUploader.Deferred();
     68               //1、计算文件的唯一标记,用于断点续传
     69               // (new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024)
     70               (new WebUploader.Uploader()).md5File(file, 0, 1024)
     71                       .progress(function(percentage) {
     72                           $('#' + file.id).find("td.state").text("正在读取文件信息...");
     73                       }).then(function(val) {
     74                           fileMd5 = val;
     75                           $('#' + file.id).find("td.state").text("成功获取文件信息...");
     76                           //获取文件信息后进入下一步
     77                           deferred.resolve();
     78                       });
     79               return deferred.promise();
     80           },
     81           //时间点2:如果有分块上传,则每个分块上传之前调用此函数
     82           beforeSend : function(block) {
     83               var deferred = WebUploader.Deferred();
     84 
     85               $.ajax({
     86                   type : "POST",
     87                   url : "{% raw %}{{url_for('.checkChunk')}}{% endraw %}",
     88                   data : {
     89                       //文件唯一标记
     90                       fileMd5 : fileMd5,
     91                       //当前分块下标
     92                       chunk : block.chunk,
     93                       //当前分块大小
     94                       chunkSize : block.end - block.start
     95                   },
     96                   dataType : "json",
     97                   success : function(response) {
     98                       if (response.ifExist) {
     99                           //分块存在,跳过
    100                           deferred.reject();
    101                       } else {
    102                           //分块不存在或不完整,重新发送该分块内容
    103                           deferred.resolve();
    104                       }
    105                   }
    106               });
    107 
    108               this.owner.options.formData.fileMd5 = fileMd5;
    109               deferred.resolve();
    110               return deferred.promise();
    111           },
    112           //时间点3:所有分块上传成功后调用此函数
    113           afterSendFile : function() {
    114               //如果分块上传成功,则通知后台合并分块
    115               $.ajax({
    116                   type : "POST",
    117                   url : "{% raw %}{{url_for('.mergeChunks')}}{% endraw %}",
    118                   data : {
    119                       fileMd5 : fileMd5,
    120                       fileSuffix:fileSuffix,
    121                       fileName:fileName,
    122                   },
    123                   success : function(response) {
    124                       console.log(response.fileName+" 上传成功")
    125                       // alert("上传成功");
    126                   }
    127               });
    128           }
    129       });
    130 
    131       var uploader = WebUploader
    132               .create({
    133                   // swf文件路径
    134                   swf : 'https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.1/Uploader.swf',
    135                   // 文件接收服务端。
    136                   server : '{% raw %}{{ url_for("upload") }}{% endraw %}',
    137                   // 选择文件的按钮。可选。
    138                   // 内部根据当前运行是创建,可能是input元素,也可能是flash.
    139                   pick : {
    140                       id : '#picker',//这个id是你要点击上传文件的id
    141                       multiple : true
    142                   },
    143                   // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
    144                   resize : true,
    145                   auto : false,
    146                   //开启分片上传
    147                   chunked : true,
    148                   chunkSize : 10 * 1024 * 1024,
    149 
    150                   accept : {
    151                       extensions : "txt,jpg,jpeg,bmp,png,zip,rar,war,pdf,cebx,doc,docx,ppt,pptx,xls,xlsx,iso,flv,mp4",
    152                       mimeTypes : '.txt,.jpg,.jpeg,.bmp,.png,.zip,.rar,.war,.pdf,.cebx,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.iso,.flv,.mp4'
    153                   }
    154 
    155               });
    156 
    157       // 当有文件被添加进队列的时候
    158       uploader.on('fileQueued', function(file) {
    159           //保存文件扩展名
    160           fileSuffix=file.ext;
    161           fileName=file.source['name'];
    162           var fileSize=file.size;
    163           var fileSizeStr="";
    164           fileSizeStr=WebUploader.Base.formatSize(fileSize);
    165           count++;
    166           $list.append(
    167                   '<tr id="' + file.id + '" class="item" flag=0>'+
    168                   '<td class="index">' + count + '</td>'+
    169                   '<td class="info">' + file.name + '</td>'+
    170                   '<td class="size">' + fileSizeStr + '</td>'+
    171                   '<td class="state">等待上传...</td>'+
    172                   '<td class="percentage"></td>'+
    173                   '<td class="operate"><button name="upload" class="btn btn-warning">开始</button><button name="delete" class="btn btn-error">删除</button></td></tr>');
    174           map.put(file.id+"",file);
    175       });
    176 
    177       // 文件上传过程中创建进度条实时显示。
    178       uploader.on('uploadProgress', function(file, percentage) {
    179           $('#' + file.id).find('td.percentage').text(
    180                   '上传中 ' + Math.round(percentage * 100) + '%');
    181       });
    182 
    183       uploader.on('uploadSuccess', function(file) {
    184           $('#' + file.id).find('td.state').text('已上传');
    185       });
    186 
    187       uploader.on('uploadError', function(file) {
    188           $('#' + file.id).find('td.state').text('上传出错');
    189       });
    190 
    191       uploader.on('uploadComplete', function(file) {
    192           uploader.removeFile(file);
    193       });
    194 
    195 
    196       uploader.on('all', function(type) {
    197           if (type === 'startUpload') {
    198               state = 'uploading';
    199           } else if (type === 'stopUpload') {
    200               state = 'paused';
    201           } else if (type === 'uploadFinished') {
    202               state = 'done';
    203           }
    204 
    205           if (state === 'uploading') {
    206               $btn.text('暂停上传');
    207           } else {
    208               $btn.text('开始上传');
    209           }
    210       });
    211 
    212       $btn.on('click', function(){
    213           if (state === 'uploading'){
    214               uploader.stop(true);
    215           } else {
    216               uploader.upload();
    217           }
    218       });
    219 
    220       $("body").on("click","#uploadTable button[name='upload']",function(){
    221           flag=$(this).parents("tr.item").attr("flag")^1;
    222           $(this).parents("tr.item").attr("flag",flag);
    223           var id=$(this).parents("tr.item").attr("id");
    224           if(flag==1){
    225               $(this).text("暂停");
    226               uploader.upload(uploader.getFile(id,true));
    227 
    228           }else{
    229               $(this).text("开始");
    230               //uploader.stop(true);
    231               uploader.stop(uploader.getFile(id,true));
    232               //uploader.skipFile(file);
    233               //uploader.removeFile(file);
    234               //uploader.getFile(id,true);
    235           }
    236       });
    237 
    238       $("body").on("click","#uploadTable button[name='delete']",function(){
    239           var id=$(this).parents("tr.item").attr("id");
    240           $(this).parents("tr.item").remove();
    241           uploader.removeFile(uploader.getFile(id,true));
    242           map.remove(id);
    243       });
    244   </script>
    245 </body>
    246 </html>
     1 <!--
     2 list.html
     3 -->
     4 <!DOCTYPE html>
     5 <html lang="zh-CN">
     6 <head>
     7   <meta charset="utf-8">
     8   <meta http-equiv="X-UA-Compatible" content="IE=edge">
     9   <meta name="viewport" content="width=device-width, initial-scale=1">
    10   <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    11   <title>Bootstrap 101 Template</title>
    12 
    13   <!-- Bootstrap -->
    14   <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
    15 
    16   <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    17   <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    18   <!--[if lt IE 9]>
    19     <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
    20     <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    21   <![endif]-->
    22   <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    23   <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    24   <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    25   <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    26 </head>
    27 <body>
    28   <div class="container-fluid">
    29     <div class="table-responsive col-md-6 col-md-offset-3">
    30         <table class="table">
    31           <tr>
    32               <td class="active">序号</td>
    33               <td class="active">文件</td>
    34           </tr>
    35           {% raw %}{% for file in files %}
    36           <tr>
    37               <td class="active">{{ files.index(file)+1 }}</td>
    38               <td class="active">{{file}}</td>
    39           </tr>
    40           {% endfor %}{% endraw %}
    41         </table>
    42     </div>
    43   </div>
    44 </body>
    45 </html>
  • 相关阅读:
    CF1359D Yet Another Yet Another Task
    【数据结构】fhq_treap
    AtCoder Beginner Contest 182 题解
    UVA11992 Fast Matrix Operations
    双指针例题
    python使用国内镜像库
    APP元素定位工具之——Weditor
    安卓ADB的常见命令的使用
    函数进阶之迭代器,递归
    函数基础之对象,嵌套,名称空间和作用域
  • 原文地址:https://www.cnblogs.com/a2534786642/p/11040887.html
Copyright © 2011-2022 走看看