需求
在头条项目中,如用户头像、文章图片等数据需要使用文件存储系统来保存
方案
- 自己搭建文件系统服务
- 选用第三方对象存储服务
我们在头条项目中使用七牛云对象存储服务 http://www.qiniu.com。
使用
- 注册
- 新建存储空间
- 使用七牛SDK完成代码实现
七牛Python SDK 网址 https://developer.qiniu.com/kodo/sdk/1242/python
安装SDK
编码
七牛提供的上传代码参考示例
from qiniu import Auth, put_file, etag
import qiniu.config
#需要填写你的 Access Key 和 Secret Key
access_key = 'Access_Key'
secret_key = 'Secret_Key'
#构建鉴权对象
q = Auth(access_key, secret_key)
#要上传的空间
bucket_name = 'Bucket_Name'
#上传后保存的文件名
key = 'my-python-logo.png'
#生成上传 Token,可以指定过期时间等
token = q.upload_token(bucket_name, key, 3600)
#要上传文件的本地路径
localfile = './sync/bbb.jpg'
ret, info = put_file(token, key, localfile)
print(info)
assert ret['key'] == key
assert ret['hash'] == etag(localfile)
项目实现
from qiniu import Auth, put_file, etag, put_data
import qiniu.config
from flask import current_app
def upload_image(file_data):
"""
上传图片到七牛
:param file_data: bytes 文件
:return: file_name
"""
# 需要填写你的 Access Key 和 Secret Key
access_key = current_app.config['QINIU_ACCESS_KEY']
secret_key = current_app.config['QINIU_SECRET_KEY']
# 构建鉴权对象
q = Auth(access_key, secret_key)
# 要上传的空间
bucket_name = current_app.config['QINIU_BUCKET_NAME']
# 上传到七牛后保存的文件名
# key = 'my-python-七牛.png'
key = None
# 生成上传 Token,可以指定过期时间等
token = q.upload_token(bucket_name, expires=1800)
# # 要上传文件的本地路径
# localfile = '/Users/jemy/Documents/qiniu.png'
# ret, info = put_file(token, key, localfile)
ret, info = put_data(token, key, file_data)
return ret['key']
上传头像、身份证图片接口
在common/utils/parser.py
import imghdr
def image_file(value):
"""
检查是否是图片文件
:param value:
:return:
"""
try:
file_type = imghdr.what(value)
except Exception:
raise ValueError('Invalid image.')
else:
if not file_type:
raise ValueError('Invalid image.')
else:
return value
toutiao/resources/user/profle.py
class PhotoResource(Resource):
"""
用户图像 (头像,身份证)
"""
method_decorators = [login_required]
def patch(self):
file_parser = RequestParser()
file_parser.add_argument('photo', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_front', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_back', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_handheld', type=parser.image_file, required=False, location='files')
files = file_parser.parse_args()
user_id = g.user_id
new_user_values = {}
new_profile_values = {}
return_values = {'id': user_id}
if files.photo:
try:
photo_url = upload_image(files.photo.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading profile photo image failed.'}, 507
new_user_values['profile_photo'] = photo_url
return_values['photo'] = current_app.config['QINIU_DOMAIN'] + photo_url
need_delete_profile = True
if files.id_card_front:
try:
id_card_front_url = upload_image(files.id_card_front.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_front image failed.'}, 507
new_profile_values['id_card_front'] = id_card_front_url
return_values['id_card_front'] = current_app.config['QINIU_DOMAIN'] + id_card_front_url
if files.id_card_back:
try:
id_card_back_url = upload_image(files.id_card_back.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_back image failed.'}, 507
new_profile_values['id_card_back'] = id_card_back_url
return_values['id_card_back'] = current_app.config['QINIU_DOMAIN'] + id_card_back_url
if files.id_card_handheld:
try:
id_card_handheld_url = upload_image(files.id_card_handheld.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_handheld image failed.'}, 507
new_profile_values['id_card_handheld'] = id_card_handheld_url
return_values['id_card_handheld'] = current_app.config['QINIU_DOMAIN'] + id_card_handheld_url
if new_user_values:
User.query.filter_by(id=user_id).update(new_user_values)
if new_profile_values:
UserProfile.query.filter_by(id=user_id).update(new_profile_values)
db.session.commit()
return return_values, 201
class PhotoResource(Resource):
"""
用户图像 (头像,身份证)
"""
method_decorators = [login_required]
def patch(self):
file_parser = RequestParser()
file_parser.add_argument('photo', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_front', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_back', type=parser.image_file, required=False, location='files')
file_parser.add_argument('id_card_handheld', type=parser.image_file, required=False, location='files')
files = file_parser.parse_args()
user_id = g.user_id
new_user_values = {}
new_profile_values = {}
return_values = {'id': user_id}
if files.photo:
try:
photo_url = upload_image(files.photo.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading profile photo image failed.'}, 507
new_user_values['profile_photo'] = photo_url
return_values['photo'] = current_app.config['QINIU_DOMAIN'] + photo_url
need_delete_profile = True
if files.id_card_front:
try:
id_card_front_url = upload_image(files.id_card_front.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_front image failed.'}, 507
new_profile_values['id_card_front'] = id_card_front_url
return_values['id_card_front'] = current_app.config['QINIU_DOMAIN'] + id_card_front_url
if files.id_card_back:
try:
id_card_back_url = upload_image(files.id_card_back.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_back image failed.'}, 507
new_profile_values['id_card_back'] = id_card_back_url
return_values['id_card_back'] = current_app.config['QINIU_DOMAIN'] + id_card_back_url
if files.id_card_handheld:
try:
id_card_handheld_url = upload_image(files.id_card_handheld.read())
except Exception as e:
current_app.logger.error('upload failed {}'.format(e))
return {'message': 'Uploading id_card_handheld image failed.'}, 507
new_profile_values['id_card_handheld'] = id_card_handheld_url
return_values['id_card_handheld'] = current_app.config['QINIU_DOMAIN'] + id_card_handheld_url
if new_user_values:
User.query.filter_by(id=user_id).update(new_user_values)
if new_profile_values:
UserProfile.query.filter_by(id=user_id).update(new_profile_values)
db.session.commit()
return return_values, 201