a2534786642

上传文件

一、自定义上传文件

 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>

 

分类:

技术点:

相关文章: