layui 上传组件后端代码分享( Python 的版本)

分享 已结 精帖
10 3844
陶先森
陶先森 2017-12-22
悬赏:20飞吻
看了社区分享了不少关于upload组件的后端示例,php、java,正好有个案例,将上传部分拆分,补下python的示例(虽然可能没人使用)。。。
环境:
python2.6,2.7,3.5测试通过
flask0.10.1
layui2.2.45(发帖时最新版)
流程:
前端多图选择上传,服务端接收文件保存本地(亦可第三方云存储),并生成图片地址返回,出现查看按钮;上传失败重试等(感谢社区分享的,但是忘记是谁了~~)。
使用flask、layui upload的好处,“简单粗暴”不多说[嘘]
贴主要的两个文件代码,前端的index.html和后端的main.py;
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui 上传组件后端代码分享(python的版本)</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='css/layui.css') }}" media="all">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" media="all">
<link href="{{ url_for('static', filename='images/favicon.ico') }}" rel="icon" type="image/x-icon" />
<link href="{{ url_for('static', filename='images/favicon.ico') }}" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
<blockquote class="layui-elem-quote">
当前位置: 首页
</blockquote>
<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="chooseList">选择图片</button>
<button type="button" class="layui-btn" id="uploadAction"><i class="layui-icon"></i>开始上传</button>
<div class="layui-upload-list">
<table class="layui-table">
<thead>
<tr>
<th>预览</th>
<th>文件名</th>
<th>大小</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="previewList"></tbody>
</table>
</div>
</div>
<script src="{{ url_for('static', filename='layui.js') }}" charset="utf-8"></script>
<script>
layui.use(['upload', 'layer'], function(){
var upload = layui.upload, layer = layui.layer, $ = layui.jquery;
//多文件列表上传
var demoListView = $('#previewList'),uploadListIns = upload.render({
elem: '#chooseList'
,url: '{{ url_for("upload_view") }}'
,method: 'POST'
,accept: 'images'
,multiple: true
,auto: false
,number: 0
,size: 2048
,bindAction: '#uploadAction'
,choose: function(obj){
var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
//读取本地文件
obj.preview(function(index, file, result){
var tr = $(['<tr id="upload-'+ index +'">'
,'<td><img src="'+ result +'" style="max-width:50px" class="layui-upload-img"></td>'
,'<td>'+ file.name +'</td>'
,'<td>'+ (file.size/1014).toFixed(1) +'kb</td>'
,'<td>等待上传</td>'
,'<td>'
,'<button class="layui-btn layui-btn-mini demo-reload layui-hide">重传</button>'
,'<button class="layui-btn layui-btn-mini layui-btn-danger demo-delete">删除</button>'
,'</td>'
,'</tr>'].join(''));
//单个重传
tr.find('.demo-reload').on('click', function(){
obj.upload(index, file);
});
//删除
tr.find('.demo-delete').on('click', function(){
delete files[index]; //删除对应的文件
tr.remove();
});
demoListView.append(tr);
});
}
,before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致
if (Object.keys(this.files).length===0) {
layer.msg("队列中无图片");
} else {
layer.load(); //上传loading
}
}
,done: function(res, index, upload){
console.log(res);
if(res.code == 0){ //上传成功
var tr = demoListView.find('tr#upload-'+ index),tds = tr.children();
tds.eq(3).html('<span style="color: #5FB878;">上传成功</span>');
tds.eq(4).html('<a href="'+res.data.src+'" target="_blank"><button class="layui-btn layui-btn-mini layui-btn-normal">查看</button></a>'); //清空操作
delete this.files[index]; //删除文件队列已经上传成功的文件
layer.closeAll('loading');
return;
}
this.error(index, upload);
}
,error: function(index, upload){
var tr = demoListView.find('tr#upload-'+ index),tds = tr.children();
tds.eq(3).html('<span style="color: #FF5722;">上传失败</span>');
tds.eq(4).find('.demo-reload').removeClass('layui-hide'); //显示重传
layer.closeAll('loading');
}
});
});
</script>
</body>
</html>

main.py
# -*- coding: utf-8 -*-
"""
UploadDemo.main
~~~~~~~~~~~~~~

This is an entry files, main applications, and some initialization operations.

Docstring conventions:
http://flask.pocoo.org/docs/0.10/styleguide/#docstrings

Comments:
http://flask.pocoo.org/docs/0.10/styleguide/#comments

:copyright: (c) 2017 by Mr.tao.
:license: MIT, see LICENSE for more details.
"""

__author__ = "Mr.tao"
__email__ = "staugur@saintic.com"

import os, datetime, random
from werkzeug import secure_filename
from flask import Flask, request, jsonify, render_template, send_from_directory, url_for

#文件上传存放的文件夹, 值为非绝对路径时,相对于项目根目录
IMAGE_FOLDER = 'static/upload/'
#生成无重复随机数
gen_rnd_filename = lambda :"%s%s" %(datetime.datetime.now().strftime('%Y%m%d%H%M%S'), str(random.randrange(1000, 10000)))
#文件名合法性验证
allowed_file = lambda filename: '.' in filename and filename.rsplit('.', 1)[1] in set(['png', 'jpg', 'jpeg', 'gif', 'bmp'])

app = Flask(__name__)
app.config.update(
SECRET_KEY = os.urandom(24),
# 上传文件夹
UPLOAD_FOLDER = os.path.join(app.root_path, IMAGE_FOLDER),
# 最大上传大小,当前16MB
MAX_CONTENT_LENGTH = 16 * 1024 * 1024
)

@app.route("/")
def index_view():
"""主页视图"""
return render_template("index.html")

@app.route('/showimg/<filename>')
def showimg_view(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

@app.route('/upload/', methods=['POST','OPTIONS'])
def upload_view():
res = dict(code=-1, msg=None)
f = request.files.get('file')
if f and allowed_file(f.filename):
filename = secure_filename(gen_rnd_filename() + "." + f.filename.split('.')[-1]) #随机命名
# 自动创建上传文件夹
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
# 保存图片
f.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
imgUrl = url_for('showimg_view', filename=filename, _external=True)
res.update(code=0, data=dict(src=imgUrl))
else:
res.update(msg="Unsuccessfully obtained file or format is not allowed")
return jsonify(res)

if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000, debug=True)

效果图:
选择文件后

上传文件后

已经算是非常简化的了,也有注释,应该好理解,上传返回是json数据即可,并不一定要按照文档描述的格式,你可以自由定义,但是要给一个字段表明上传成功。
一时间只想出这些(懒),就写到这吧,补充代码传到github了, https://github.com/staugur/CherryWaterfall/tree/UploadDemo
水平有限,请勿往死地拍砖,[围观]
回帖
本帖已设置禁止回复