Как изменить / заменить изображение S3 с помощью Python и библиотеки Chalice?
Я пишу лямбда-функцию, которая срабатывает каждый раз, когда пользователь загружает изображение на S3. Основная цель функции - сжать изображение, возможно, переименовав его в процессе. Чтобы достичь этого, функция состоит в том, чтобы извлечь вновь загруженное изображение, сжать его, загрузить вновь сжатое изображение и удалить исходный файл:
@app.on_s3_event(bucket=settings.BUCKET_NAME, events=['s3:ObjectCreated:*'])
def compress(event):
# download the resource
s3.Bucket(settings.BUCKET_NAME).download_file(key, local_file_path)
# compress the image
...
# rename the file, if necessary (change extension, etc.)
...
# upload the new image
s3.Object(settings.BUCKET_NAME, output_path).put(Body=open(compressed_path, 'rb'))
# remove original image
s3.Object(settings.BUCKET_NAME, event.key).delete()
Так что, если я загружу изображение с именем sample.png
на S3, он сжимается и переименовывается, скажем, sample.jpg
; а также sample.png
будет удален позже.
Проблема, однако, заключается в том, что решение приведет к бесконечной рекурсии. Причина заключается в том, что загрузка сжатого изображения снова вызовет лямбда-функцию, вызывая тем самым загрузку снова, тем самым сжимая уже сжатое изображение, тем самым загружая его снова. До бесконечности.
Мой друг предложил два возможных решения: кэшировать имя сжатого изображения, сохраняя его где-то в отдельном файле корзины S3, и предотвращать загрузку кэшированных имен файлов более одного раза; и изменить exif/metada сжатого изображения так, чтобы лямбда могла сказать, какие файлы уже были сжаты, указывая, что функция не должна выполняться, что предотвратит повторное сжатие.
Первая идея склонна к проблемам, которые могут возникнуть, когда несколько файлов загружаются на сервер одновременно, по крайней мере теоретически. Вторая идея может потребовать сторонней библиотеки, такой как piexif, но это та, которую я сейчас рассматриваю.
У вас есть лучший способ решения этой проблемы? Или я вообще занимаюсь сжатием (кроме рекурсивной загрузки и выгрузки) прямо с самого начала? Я имею в виду, возможно, я могу сжать изображения S3, не выполняя процедуру загрузки-сжатия-загрузки-удаления.
1 ответ
Привет, поскольку вы конвертируете его в другой формат, будет проще, если вы вызовете свою лямбда-функцию для загруженного формата файла, что предотвратит ненужный бесконечный цикл.
Предположим, изображения загружаются в формате .jpeg, а вы сжимаете и конвертируете их в .png. Теперь, поскольку недавно обновленное изображение находится в формате .png, ваша лямбда-функция не будет запускаться.