# 文件上传与邮件发送 ### 原生实现 - 模板文件 ```html <form method="post" enctype="multipart/form-data"> <input type="file" name="photo" /><br /> <input type="submit" value="上传" /> </form> ``` - 视图函数 ```python import os # 配置上传文件保存目录 app.config[‘UPLOADED_FOLDER‘] = os.path.join(os.getcwd(), ‘static/upload‘) @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): if request.method == ‘POST‘: # 获取上传对象 photo = request.files.get(‘photo‘) if photo: # 拼接保存路径名 pathname = os.path.join(app.config[‘UPLOADED_FOLDER‘], photo.filename) # 保存上传文件 photo.save(pathname) return ‘上传成功‘ else: return ‘上传失败‘ return render_template(‘upload.html‘) ``` - 上传限制设置 ```python # 允许上传的文件后缀 ALLOWED_SUFFIX = set([‘png‘, ‘jpg‘, ‘jpeg‘, ‘gif‘]) # 判断是否是允许的后缀 def allowed_file(filename): return ‘.‘ in filename and filename.rsplit(‘.‘, 1)[1] in ALLOWED_SUFFIX # 限制请求大小 app.config[‘MAX_CONTENT_LENGTH‘] = 1024 * 1024 * 8 # 展示上传的图片 @app.route(‘/uploaded/<filename>‘) def uploaded(filename): return send_from_directory(app.config[‘UPLOADED_FOLDER‘], filename) @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): img_url = None if request.method == ‘POST‘: # 获取上传对象 photo = request.files.get(‘photo‘) if photo and allowed_file(photo.filename): # 拼接保存路径名 pathname = os.path.join(app.config[‘UPLOADED_FOLDER‘], photo.filename) # 保存上传文件 photo.save(pathname) # 构造上传文件的url img_url = url_for(‘uploaded‘, filename=photo.filename) return render_template(‘upload.html‘, img_url=img_url) ``` ### flask-uploads - 说明:极大的的简化了文件上传相关的操作,使用非常方面。 - 安装:`pip install flask-uploads` - 使用: - 配置 ```python from flask_uploads import UploadSet, IMAGES from flask_uploads import configure_uploads from flask_uploads import patch_request_class import os app.config[‘UPLOADED_PHOTOS_DEST‘] = os.getcwd() app.config[‘MAX_CONTENT_LENGTH‘] = 8 * 1024 * 1024 # 创建上传对象 photos = UploadSet(‘photos‘, IMAGES) # 配置上传对象 configure_uploads(app, photos) # 配置上传文件大小,默认为64M, # 若设置为None,则以MAX_CONTENT_LENGTH配置为准 patch_request_class(app, size=None) ``` - 视图函数 ```python @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): img_url = None if request.method == ‘POST‘: # 获取上传对象 photo = request.files.get(‘photo‘) if photo: # 保存上传文件,返回文件名 filename = photos.save(photo) # 根据文件名获取上传文件的URL img_url = photos.url(filename) return render_template(‘upload.html‘, img_url=img_url) ``` ### 综合使用 - 要求:结合flask-bootstrap、flask-wtf、flask-uploads等完成文件上传 - 使用: - 配置 ```python from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed, FileRequired from wtforms import SubmitField from flask_uploads import UploadSet, IMAGES from flask_uploads import configure_uploads from flask_uploads import patch_request_class from flask_bootstrap import Bootstrap import os bootstrap = Bootstrap(app) app.config[‘SECRET_KEY‘] = ‘123456‘ app.config[‘MAX_CONTENT_LENGTH‘] = 8 * 1024 * 1024 app.config[‘UPLOADED_PHOTOS_DEST‘] = os.path.join(os.getcwd(), ‘static/upload‘) photos = UploadSet(‘photos‘, IMAGES) configure_uploads(app, photos) patch_request_class(app, size=None) class UploadForm(FlaskForm): photo = FileField(‘头像‘, validators=[FileRequired(message=‘请选择文件‘), FileAllowed(photos, message=‘只能上传图片文件‘)]) submit = SubmitField(‘上传‘) ``` - 视图函数 ```python @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): img_url = None form = UploadForm() if form.validate_on_submit(): photo = form.photo.data filename = photos.save(photo) img_url = photos.url(filename) return render_template(‘upload.html‘, form=form, img_url=img_url) ``` - 模板文件 ```html {% extends ‘bootstrap/base.html‘ %} {% from ‘bootstrap/wtf.html‘ import quick_form %} {% block title %}完整的文件上传{% endblock %} {% block content %} <div class="container"> {% if img_url %} <img src="{{ img_url }}"> {% endif %} {{ quick_form(form) }} </div> {% endblock %} ``` - 生成随机文件名 ```python def random_string(length=32): import random base_str = ‘abcdefghijklmnopqrstuvwxyz1234567890‘ return ‘‘.join(random.choice(base_str) for i in range(length)) @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): 。。。 # 提取文件后缀 suffix = os.path.splitext(photo.filename)[1] # 生成随机文件名 filename = random_string() + suffix # 保存文件 photos.save(photo, name=filename) 。。。 ``` - 生成缩略图:PIL模块(只支持py2,要支持py3需要安装pillow) ```python from PIL import Image @app.route(‘/upload/‘, methods=[‘GET‘, ‘POST‘]) def upload(): ... # 拼接完整文件路径名 pathname = os.path.join(app.config[‘UPLOADED_PHOTOS_DEST‘], filename) # 打开文件 img = Image.open(pathname) # 设置大小 img.thumbnail((64, 64)) # 保存图片 img.save(pathname) ... ``` ### flask-mail - 说明:专门用于邮件发送的扩展库,使用非常方便。 - 安装:`pip install flask-mail` - 使用: ```python from flask_mail import Mail, Message import os # 邮件发送配置,一定要放在创建Mail对象之前 app.config[‘MAIL_SERVER‘] = ‘smtp.1000phone.com‘ # 用户名 app.config[‘MAIL_USERNAME‘] = ‘[email protected]‘ # 密码 app.config[‘MAIL_PASSWORD‘] = os.getenv(‘MAIL_PASSWORD‘, ‘123456‘) # 创建发送邮件的对象 mail = Mail(app) @app.route(‘/send/‘) def send(): # 创建邮件消息对象 msg = Message(‘账户激活‘, recipients=[‘[email protected]‘], sender=app.config[‘MAIL_USERNAME‘]) msg.html = ‘恭喜你,中奖了!!!‘ # 发送邮件 mail.send(msg) return ‘邮件已发送‘ ``` - 封装函数发送邮件 ```python def send_mail(subject, to, template, *args, **kwargs): if isinstance(to, list): recipients = to elif isinstance(to, str): recipients = to.split(‘,‘) else: raise Exception(‘邮件接收者参数类型有误‘) # 创建邮件消息对象 msg = Message(subject, recipients=recipients, sender=app.config[‘MAIL_USERNAME‘]) # 将邮件模板渲染后作为邮件内容 msg.html = render_template(template, *args, **kwargs) # 发送邮件 mail.send(msg) ``` - 异步发送邮件 ```python from flask import current_app # 异步发送邮件任务 def async_send_mail(app, msg): # 邮件发送必须在程序上下文 # 新的线程中没有上下文,因此需要手动创建 with app.app_context(): mail.send(msg) # 封装函数发送邮件 def send_mail(subject, to, template, *args, **kwargs): if isinstance(to, list): recipients = to elif isinstance(to, str): recipients = to.split(‘,‘) else: raise Exception(‘邮件接收者参数类型有误‘) # 创建邮件消息对象 msg = Message(subject, recipients=recipients, sender=app.config[‘MAIL_USERNAME‘]) # 将邮件模板渲染后作为邮件内容 msg.html = render_template(template, *args, **kwargs) # 异步发送邮件 # current_app是app的代理对象 # 根据代理对象current_app找到原始的app app = current_app._get_current_object() # 创建线程 thr = Thread(target=async_send_mail, args=(app, msg)) # 启动线程 thr.start() # 返回线程 return thr ``` ###环境变量 - windows: - 设置:`set 环境变量名=值` - 获取:`set 环境变量名` - linux: - 导出:`export 环境变量名=值` - 获取:`echo $环境变量名` - 代码: - `os.getenv(‘环境变量名‘, ‘123456‘)`
原文地址:https://www.cnblogs.com/liangliangzz/p/10221980.html
时间: 2024-11-09 19:13:53