diff --git a/mediathread/assetmgr/urls.py b/mediathread/assetmgr/urls.py index eafb65a81..7050c37f4 100644 --- a/mediathread/assetmgr/urls.py +++ b/mediathread/assetmgr/urls.py @@ -78,7 +78,7 @@ path('pdfjs//', PDFViewerDetailView.as_view(), {}, name='pdfjs'), - path('sign_s3/', S3SignView.as_view()), + path('sign_s3/', S3SignView.as_view(), name='s3sign'), # Load this CSS asset as a TemplateView so we can use the static # template tag. diff --git a/mediathread/assetmgr/utils.py b/mediathread/assetmgr/utils.py index 00224581f..b9ec249d5 100644 --- a/mediathread/assetmgr/utils.py +++ b/mediathread/assetmgr/utils.py @@ -1,15 +1,67 @@ -from urllib.parse import urlparse import boto3 -from s3sign.utils import create_presigned_url, s3_config +import requests +from django.conf import settings +from os.path import basename, splitext, join +from PIL import Image +from pi_heif import register_heif_opener +from s3sign.utils import create_presigned_url, s3_config, upload_file +from urllib.parse import urlparse + +def get_s3_private_bucket_name() -> str: + return getattr( + settings, + 'S3_PRIVATE_STORAGE_BUCKET_NAME', + 'mediathread-private-uploads') -def get_signed_s3_url(url, bucket, aws_key, aws_secret): - s3_client = boto3.client( + +def get_s3_client(aws_key, aws_secret): + return boto3.client( 's3', config=s3_config, aws_access_key_id=aws_key, aws_secret_access_key=aws_secret) + +def get_signed_s3_url(url: str, bucket: str, aws_key: str, aws_secret: str): + s3_client = get_s3_client(aws_key, aws_secret) + url = urlparse(url) object_name = url.path.lstrip('/') object_name = object_name.replace(bucket + '/', '') return create_presigned_url(s3_client, bucket, object_name, 3600) + + +def convert_heic_to_jpg( + url: str, request: object, bucket: str, + aws_key: str, aws_secret: str +) -> str: + """ + Given an heic image url, convert it to a JPEG. This comprises a + few steps: + * Download the file + * Do the conversion + * Upload jpeg to S3 + * Return new url + """ + response = requests.get(url, stream=True) + + # Sort out the new filename + parsed_url = urlparse(url) + filename = splitext(basename(parsed_url.path))[0] + filename = filename + '.jpg' + + # Open the file and convert it + register_heif_opener() + im = Image.open(response.raw) + rgb_im = im.convert('RGB') + tmp_jpeg = join('/tmp/', filename) + rgb_im.save(tmp_jpeg) + + # upload to S3, return source url + mime_type = 'image/jpeg' + private = True + data = upload_file( + get_s3_client(aws_key, aws_secret), bucket, mime_type, object_name, + max_file_size, acl, expiration_time, private + ) + print(data) diff --git a/mediathread/assetmgr/views.py b/mediathread/assetmgr/views.py index 9636b5bb7..3b5f857c3 100644 --- a/mediathread/assetmgr/views.py +++ b/mediathread/assetmgr/views.py @@ -37,6 +37,9 @@ Asset, Source, ExternalCollection, SuggestedExternalCollection ) +from mediathread.assetmgr.utils import ( + get_signed_s3_url, get_s3_private_bucket_name, convert_heic_to_jpg +) from mediathread.djangosherd.api import DiscussionIndexResource from mediathread.djangosherd.models import SherdNote, DiscussionIndex from mediathread.djangosherd.views import create_annotation, edit_annotation, \ @@ -375,6 +378,19 @@ def post(self, request, *args, **kwargs): width = request.POST.get('width') height = request.POST.get('height') + if url.endswith('.heic') or url.endswith('.heif'): + # Convert to JPG + s3_private_bucket = get_s3_private_bucket_name() + signed_url = get_signed_s3_url( + url, s3_private_bucket, + settings.AWS_ACCESS_KEY, + settings.AWS_SECRET_KEY) + + # Pass in the signed url because we need to download it. + url = convert_heic_to_jpg( + signed_url, request, s3_private_bucket, + settings.AWS_ACCESS_KEY, settings.AWS_SECRET_KEY) + # If the form passed in a valid label, use it. lbl = request.POST.get('label') if lbl and lbl in Asset.primary_labels: diff --git a/requirements.txt b/requirements.txt index 071f5827c..0f947859f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -143,6 +143,8 @@ click-plugins>=1.1.1 wcwidth==0.2.5 django-celery-results<2.6.0 +Pillow==11.1.0 +pi-heif==0.21.0 # memcached pylibmc==1.6.3;sys_platform == "linux" and python_version<"3.9"