Как добавить пользовательские метаданные S3 при использовании django-storages
Я использую django 3.1.0 с django-storages 1.12.3. Я использую бэкенд S3 для хранения медиафайлов (Minio). Я пытаюсь отправить файл на S3 и включить дополнительные метаданные пользователя в объект S3. Эти дополнительные метаданные поступают из POST-запроса, используемого для загрузки файла в django. В S3 пользовательские метаданные могут быть добавлены путем включения дополнительных пар ключ-значение в HTTP-заголовок POST-запроса, отправляемого на сервер S3 при загрузке файла, где пользовательские ключи будут иметь префикс 'X-Amz-Meta-'.
Я использую FileField в модели django, а файлы загружаются с помощью конечной точки REST API. Насколько я понимаю, когда django получает файл, он временно хранит его, а затем, при сохранении FielField на экземпляре модели, файл размещается на сервере S3. Я хочу изменить поток, чтобы пользовательские метаданные брались из запроса и включались в отправку на сервер S3.
Есть идеи, как я могу взять данные из начального запроса и передать их в заголовок POST-запроса, отправляемого в S3?
Есть два возможных варианта:
1. Использовать пользовательский класс хранения
Одним из вариантов может быть использование пользовательского класса хранения для вашего FileField, в котором вы перезаписываете метод S3Boto3Storage.get_object_parameters, как предлагается в документации .
from storages.backends.s3boto3 import S3Boto3Storage
class CustomStorage(S3Boto3Storage):
def get_object_parameters():
# Your code here
pass
А в вашей модели:
from django.db import models
import CustomStorage
class MyModel(models.Model):
image_file = models.FileField(storage=CustomStorage(), upload_to='my/path)
2. Загрузите файл вручную с помощью boto3
Другим вариантом будет использование boto3 для загрузки файла вручную ( Документация.
Вы можете установить метаданные объекта с помощью следующего кода, взятого из этого ответа:
import boto3
s3 = boto3.resource('s3')
s3.meta.client.upload_file(Filename, bucketname, key, ExtraArgs={"Metadata": {"metadata1":"ImageName","metadata2":"ImagePROPERTIES" ,"metadata3":"ImageCREATIONDATE"}})
После этого вы должны установить name свойство FileField на ключ в S3 Bucket, как описано в этом ответе.
object.filefield.name = 'file/key/in/bucket'