Flask保存图片与展示

配置项

为了方便的图片的保存与展示,可以在 配置文件中,指明 图片资源的路径

import os
​
​
class Config(object):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'mysql://root:mysql@127.0.0.1:3306/day08'
    SQLALCHEMY_TRACK_MODIFICATIONS = False# 构建项目所在的 绝对路径,也就是 day08 的绝对路径
    BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
    # 自己指明的 图片上传路径
    MEDIA_ROOT = os.path.join(BASE_DIR, 'MEDIA/')
模型类
from app.extensions import db
from datetime import datetime
​
​
# 分类: id、name
class Cate(db.Model):
    __tablename__ = 'tb_cate'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(32), unique=True, nullable=False)
​
​
# 新闻: id、title、content、count、img、time、cate_id
class News(db.Model):
    __tablename__ = 'tb_news'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(32), unique=True, nullable=False)
    content = db.Column(db.Text)
    count = db.Column(db.Integer, default=0)
    img = db.Column(db.String(256))  # 图片字段中,存放的是  图片地址,并不是图片本身
    time = db.Column(db.DateTime, default=datetime.now)
    cate_id = db.Column(db.Integer, db.ForeignKey('tb_cate.id'))
    # 关系
    cate = db.relationship('Cate', backref='news')
工具集

自定义函数,将图片保存到本地

import os
from uuid import uuid4
from flask import current_app  # current_app 属于应用上下文,代表项目中的app本身
​
​
def img_upload(img):
    if not img:
        return None# 将图片名按照 .  进行切分, 找到最后一个元素,也就是  文件的后缀名
    end_name = img.filename.rsplit('.')[-1]# 通过文件的后缀名判断 身份为 合法的  图片
    if end_name not in ['jpg', 'png', 'gif', 'jpeg']:
        return None# 将 图片对象 存入 本地,然后将 路径 存入 数据库
    MEDIA = current_app.config['MEDIA_ROOT']  # 从app的配置项,取出 MEDIA的路径
    filename = str(uuid4()) + '.' + end_name  # 为了生成一个不重复的 文件名
    img_path = os.path.join(MEDIA, filename)  # 将路径和文件名拼接在一起,方便保存文件
​
    img.save(img_path)  # 将图片对象保存到 本地return filename
视图

图片上传
上传图片的逻辑, 和一般的 添加数据流程一样,只是多了一步: 将图片对象保存到本地

class NewsView(Resource):
    def post(self):
        # 1. 创建解析参数的对象
        parser = reqparse.RequestParser()
        # 2. 指明需要解析的参数
        parser.add_argument('title', type=str, location='form', required=True)
        parser.add_argument('content', type=str, location='form')
        parser.add_argument('count', type=int, location='form', default=0)
        parser.add_argument('cate_id', type=int, location='form', required=True)
        parser.add_argument('img', type=FileStorage, location='files')# 3. 获取具体的参数
        args = parser.parse_args()
​
        title = args.get('title')
        content = args.get('content')
        count = args.get('count')
        cate_id = args.get('cate_id')
        img = args.get('img')# 利用自定义函数,将图片保存到本地
        filename = img_upload(img)# 4. 创建对象, 注意:图片存储的只是 从media之后的  图片路径
        news = News(title=title, content=content, count=count, img=filename, cate_id=cate_id)
        # 5. 添加到 事务中
        db.session.add(news)
        # 6. 提交事务
        try:
            db.session.commit()
        except:
            return {
                       'msg': '添加失败'
                   }, 500
        # 7. 返回响应
        return {
                   'id': news.id,
                   'title': news.title,
                   'img': news.img
               }, 201

图片展示
图片展示,实际就是 将 图片内容读取为文件流,做为响应返回

http://127.0.0.1:5000/media/filename

class ImgView(Resource):
    def get(self, filename):
        # 1. 从配置项中读取 media目录的 路径
        MEDIA = current_app.config['MEDIA_ROOT']
        # 2. 拼接除图片的完成路径
        img_path = os.path.join(MEDIA, filename)# 3. 按照二进制方式打开文件,读到的内容为 二进制文件流,方便接下来的网络传输
        try:
            with open(img_path, 'rb') as f:
                img = f.read()
        except FileNotFoundError:
            return None, 404# 4. 自定义响应
        resp = make_response(img)
        # 5. 声明响应体的类型 为  图片
        resp.headers['Content-Type'] = 'image/png'
        # 6. 返回响应
        return resp
# 路由匹配,获取文件名

api.add_resource(ImgView, '/media/<string:filename>')
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值