65 lines
1.9 KiB
Python
65 lines
1.9 KiB
Python
import re
|
|
import uuid
|
|
|
|
import boto3
|
|
from flask import current_app
|
|
|
|
IMAGE_MIME_TYPES = set(['image/png', 'image/jpg', 'image/gif'])
|
|
AVATAR_MAX_SIZE = 2 * 1024 * 1024 # 2MB
|
|
|
|
|
|
class AvatarException(Exception):
|
|
pass
|
|
|
|
|
|
def allowed_avatar_type(mimetype):
|
|
if mimetype not in IMAGE_MIME_TYPES:
|
|
raise AvatarException("Unacceptable file type: {0}".format(mimetype))
|
|
return True
|
|
|
|
|
|
def extract_avatar_filename(url):
|
|
match = re.search(r'avatars/(\d+\.\w+\.\w+)$', url)
|
|
if match:
|
|
return match.group(1)
|
|
else:
|
|
raise AvatarException("Unable to extract avatar filename from %s" % url)
|
|
|
|
|
|
def construct_avatar_url(filename):
|
|
S3_BUCKET = current_app.config['S3_BUCKET']
|
|
return "https://%s.s3.amazonaws.com/avatars/%s" % (S3_BUCKET, filename)
|
|
|
|
|
|
def remove_avatar(url, user_id):
|
|
S3_BUCKET = current_app.config['S3_BUCKET']
|
|
filename = extract_avatar_filename(url)
|
|
user_match = re.search(r'^(\d+)\.\w+\.\w+$', filename)
|
|
if user_match and user_match.group(1) == str(user_id):
|
|
s3 = boto3.resource('s3')
|
|
s3.Object(S3_BUCKET, 'avatars/' + filename).delete()
|
|
|
|
|
|
def sign_avatar_upload(mimetype, user_id):
|
|
S3_BUCKET = current_app.config['S3_BUCKET']
|
|
if mimetype and allowed_avatar_type(mimetype):
|
|
ext = mimetype.replace('image/', '')
|
|
filename = "{0}.{1}.{2}".format(user_id, uuid.uuid4().hex, ext)
|
|
key = "avatars/" + filename
|
|
s3 = boto3.client('s3')
|
|
presigned_post = s3.generate_presigned_post(
|
|
Bucket=S3_BUCKET,
|
|
Key=key,
|
|
Fields={"acl": "public-read", "Content-Type": mimetype},
|
|
Conditions=[
|
|
{"acl": "public-read"},
|
|
{"Content-Type": mimetype},
|
|
["content-length-range", 0, AVATAR_MAX_SIZE]
|
|
],
|
|
ExpiresIn=3600
|
|
)
|
|
return {
|
|
"data": presigned_post,
|
|
"url": construct_avatar_url(filename)
|
|
}
|