代码改变世界

Flask实现图片的上传、下载及展示

  idea555  阅读(3794)  评论(1编辑  收藏  举报

用Flask处理图片非常容易,这一篇学习一下图片的上传、下载及展示。还是以实例代码演示为主。

首先,实现一个简单的上传(过程中未做任何处理,只是为了演示)
 

点击选择图片,输入李四:

HTML代码:

  1.  
    <!DOCTYPE html>
  2.  
    <html lang="en">
  3.  
    <head>
  4.  
    <meta charset="UTF-8">
  5.  
    <title>Title</title>
  6.  
    </head>
  7.  
    <body>
  8.  
    <div>
  9.  
    <form method="post" action="http://localhost:5000/up_photo" enctype="multipart/form-data">
  10.  
    <input type="file" size="30" name="photo"/>
  11.  
    <br>
  12.  
    <input type="text" class="txt_input" name="name" style="margin-top:15px;"/>
  13.  
    <input type="submit" value="提交信息" class="button-new" style="margin-top:15px;"/>
  14.  
    </form>
  15.  
    </div>
  16.  
    </body>
  17.  
    </html>

 

点击提交信息后,通过 http://localhost:5000/up_photo,传递到后台对应的路由处理,查看控制台:

 

后台接收的路由代码:

  1.  
    basedir = os.path.abspath(os.path.dirname(__file__))
  2.  
     
  3.  
    @app.route('/up_photo', methods=['post'])
  4.  
    def up_photo():
  5.  
    img = request.files.get('txt_photo')
  6.  
    username = request.form.get("name")
  7.  
    path = basedir+"/static/photo/"
  8.  
    file_path = path+img.filename
  9.  
    img.save(file_path)
  10.  
    print '上传头像成功,上传的用户是:'+username
  11.  
    return render_template('index.html')

此时,我们查看static/photo时,已经可以看到我们点击上传的图片了。

以上是最简单的一个文件上传示例,我们实际使用中基本不可能这样去写,通常会做一些处理。例如:上传后做图片名称唯一性的处理、限制上传文件的类型、无论上传成功或者失败,都去做一些返回提示等等。
 

 

限制上传文件类型,例如,我们希望用户上传的文件为图片类型

  1.  
    ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'gif', 'GIF'])
  2.  
     
  3.  
    def allowed_file(filename):
  4.  
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

上面的代码片段通过截取上传文件的后缀名,判断是否是属于我们期望用户上传的类型。
 

 

更改上传图片名称,防止重名

 

这里我们使用日期加随机数生成图片名,做一个生成字符串的工具类

 

  1.  
    #-*-coding:utf-8-*-
  2.  
    import datetime
  3.  
    import random
  4.  
    class Pic_str:
  5.  
    def create_uuid(self): #生成唯一的图片的名称字符串,防止图片显示时的重名问题
  6.  
    nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S"); # 生成当前时间
  7.  
    randomNum = random.randint(0, 100); # 生成的随机整数n,其中0<=n<=100
  8.  
    if randomNum <= 10:
  9.  
    randomNum = str(0) + str(randomNum);
  10.  
    uniqueNum = str(nowTime) + str(randomNum);
  11.  
    return uniqueNum;

 

当我们点击图片上传,选择图片点击提交后,页面返回提示信息如下图:

 

此时看我们工程下的upload文件夹,唯一名称的图片已经上传成功

 

图片的下载

  1.  
    @app.route('/download/<string:filename>', methods=['GET'])
  2.  
    def download(filename):
  3.  
    if request.method == "GET":
  4.  
    if os.path.isfile(os.path.join('upload', filename)):
  5.  
    return send_from_directory('upload', filename, as_attachment=True)
  6.  
    pass

 

图片的展示

  1.  
    # show photo
  2.  
    @app.route('/show/<string:filename>', methods=['GET'])
  3.  
    def show_photo(filename):
  4.  
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
  5.  
    if request.method == 'GET':
  6.  
    if filename is None:
  7.  
    pass
  8.  
    else:
  9.  
    image_data = open(os.path.join(file_dir, '%s' % filename), "rb").read()
  10.  
    response = make_response(image_data)
  11.  
    response.headers['Content-Type'] = 'image/png'
  12.  
    return response
  13.  
    else:
  14.  
    pass

 

完整示例代码

  1.  
    #encoding:utf-8
  2.  
    #!/usr/bin/env python
  3.  
    from werkzeug.utils import secure_filename
  4.  
    from flask import Flask, render_template, jsonify, request, make_response, send_from_directory, abort
  5.  
    import time
  6.  
    import os
  7.  
    from strUtil import Pic_str
  8.  
    import base64
  9.  
     
  10.  
    app = Flask(__name__)
  11.  
    UPLOAD_FOLDER = 'upload'
  12.  
    app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
  13.  
    basedir = os.path.abspath(os.path.dirname(__file__))
  14.  
    ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'gif', 'GIF'])
  15.  
     
  16.  
    def allowed_file(filename):
  17.  
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
  18.  
     
  19.  
     
  20.  
    @app.route('/upload')
  21.  
    def upload_test():
  22.  
    return render_template('up.html')
  23.  
     
  24.  
     
  25.  
    # 上传文件
  26.  
    @app.route('/up_photo', methods=['POST'], strict_slashes=False)
  27.  
    def api_upload():
  28.  
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
  29.  
    if not os.path.exists(file_dir):
  30.  
    os.makedirs(file_dir)
  31.  
    f = request.files['photo']
  32.  
    if f and allowed_file(f.filename):
  33.  
    fname = secure_filename(f.filename)
  34.  
    print fname
  35.  
    ext = fname.rsplit('.', 1)[1]
  36.  
    new_filename = Pic_str().create_uuid() + '.' + ext
  37.  
    f.save(os.path.join(file_dir, new_filename))
  38.  
     
  39.  
    return jsonify({"success": 0, "msg": "上传成功"})
  40.  
    else:
  41.  
    return jsonify({"error": 1001, "msg": "上传失败"})
  42.  
     
  43.  
    @app.route('/download/<string:filename>', methods=['GET'])
  44.  
    def download(filename):
  45.  
    if request.method == "GET":
  46.  
    if os.path.isfile(os.path.join('upload', filename)):
  47.  
    return send_from_directory('upload', filename, as_attachment=True)
  48.  
    pass
  49.  
     
  50.  
     
  51.  
    # show photo
  52.  
    @app.route('/show/<string:filename>', methods=['GET'])
  53.  
    def show_photo(filename):
  54.  
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
  55.  
    if request.method == 'GET':
  56.  
    if filename is None:
  57.  
    pass
  58.  
    else:
  59.  
    image_data = open(os.path.join(file_dir, '%s' % filename), "rb").read()
  60.  
    response = make_response(image_data)
  61.  
    response.headers['Content-Type'] = 'image/png'
  62.  
    return response
  63.  
    else:
  64.  
    pass
  65.  
     
  66.  
     
  67.  
    if __name__ == '__main__':
  68.  
    app.run(debug=True)

基本示例就以上这些了!
原文章地址:https://blog.csdn.net/weixin_36380516/article/details/80347192

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示