flask:上传图片以md5二级目录存储服务器并提供完整图片地址

1 flask基本配置

# coding=utf-8
import os
import hashlib

将以下的配置写入配置文件settings.py中
UPLOAD_FOLDER = '/static/tmp/uploads'
ALLOWED_EXTENSIONS = set(['bmp', 'png', 'jpg', 'jpeg', 'gif'])

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SERVER_USER_TMP_UPLOADS = os.path.join(BASE_DIR, "static", "tmp", "uploads")
SERVER_USER_UPLOADS = os.path.join(BASE_DIR, "static", "user", "uploads")
FLASK_USER_UPLOADS = os.path.join("static", "user", "uploads")

SERVER_ADDR = "http://47.xx.1.25"

 

2 用到的主要函数,主要逻辑在第三步

# 验证图片拓展名
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

# 图片生成md5值作为唯一ID
def md5_file(file_path):
    md5_obj = hashlib.md5()
    with open(file_path, 'rb') as file_obj:
        md5_obj.update(file_obj.read())
    file_md5_id = md5_obj.hexdigest()
    return file_md5_id

# 生成图片存储的二级目录和新的md5图片名
def md5_save_dir(img_id,filename):
    img_id = str(img_id)
    first_path = img_id[0:2]
    second_path = img_id[2:4]
    prefix = img_id
    suffix = filename.rsplit('.')[1]
    md5_filename = prefix + '.' + suffix
    relative_path = os.path.join(first_path,second_path)
    return relative_path,md5_filename

 

3 主要逻辑

# 上传处理的主要逻辑
@bp.route("/api/v1/upload", methods=['POST'])
def upload():
    if request.method == "POST":
        # 接收图先检验,如果图片存在并且是允许的文件类型

        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            # 比如图片名字:hello.jpg
            # 图片临时绝对路径,默认当前项目目录的static下,比如/data/www/hello/static/tmp/uploads
            absolute_path = os.path.join(SERVER_USER_TMP_UPLOADS, filename)
            #/data/www/hello/static/tmp/uploads/hello.jpg
            file.save(absolute_path)

        # 计算图片md5值作为图片ID返回,此处计算md5过程产生的时间差
        md5_t1 = time.time()
        img_id = md5_file(absolute_path)
        md5_delta = (time.time() - md5_t1) * 1000

        # 根据图片ID(即md5)返回图片前两节目录和最终md5名字,比如:615fa43bd047d1b189be52e35591d744
        rela_path, md5_name = md5_save_dir(img_id, file.filename)
        # 比如:61/5f,615fa43bd047d1b189be52e35591d744.jpg

        # 创建md5的两级文件夹,比如/data/www/hello/static/user/uploads/61/5f
        md5_absolute_path = os.path.join(SERVER_USER_UPLOADS, rela_path)
        if not os.path.isdir(md5_absolute_path):
            os.makedirs(md5_absolute_path)

        # 在md5文件夹下面用图片另存为md5名字的图片
        md5_name = secure_filename(md5_name)
        md5_absfile_path = os.path.join(md5_absolute_path, md5_name)
        shutil.move(absolute_path, md5_absfile_path)
        print("图片在服务器绝对路径", md5_absfile_path)
        # 比如:/data/www/hello/static/user/uploads/61/5f/615fa43bd047d1b189be52e35591d744.jpg

        md5_relative_path = os.path.join(FLASK_USER_UPLOADS, rela_path)
        md5_relfile_path = os.path.join(md5_relative_path, md5_name)
        print("图片在web访问时的静态文件路径", md5_relfile_path)
        # 比如:/static/user/uploads/61/5f/615fa43bd047d1b189be52e35591d744.jpg
        # 然后web访问静态资源时,由于nginx做了静态资源处理,会自动域名+相对地址即静态文件的地址
        # 比如:http://xxx.xxxx.xxx/static/user/uploads/61/5f/615fa43bd047d1b189be52e35591d744.jpg

        full_img_path = os.path.join(SERVER_ADDR, md5_relfile_path)
        # 比如:http://xxx.xxxx.xxx/static/user/uploads/61/5f/615fa43bd047d1b189be52e35591d744.jpg

 

精简版:

@bp.route("/api/v1/upload", methods=['POST'])
def upload():
    if request.method == "POST":

        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            absolute_path = os.path.join(SERVER_USER_TMP_UPLOADS, filename)
            file.save(absolute_path)

        img_id = md5_file(absolute_path)
        rela_path, md5_name = md5_save_dir(img_id, file.filename)
        md5_absolute_path = os.path.join(SERVER_USER_UPLOADS, rela_path)
        if not os.path.isdir(md5_absolute_path):
            os.makedirs(md5_absolute_path)

        md5_name = secure_filename(md5_name)
        md5_absfile_path = os.path.join(md5_absolute_path, md5_name)
        shutil.move(absolute_path, md5_absfile_path)
        md5_relative_path = os.path.join(FLASK_USER_UPLOADS, rela_path)
        md5_relfile_path = os.path.join(md5_relative_path, md5_name)
        full_img_path = os.path.join(SERVER_ADDR, md5_relfile_path)

        data={}
        data['id']=img_id
        data['img_url']=full_img_path
        return jsonify(data)

 

posted @ 2018-05-28 18:04  Adamanter  阅读(989)  评论(0编辑  收藏  举报