Как добавить пользовательские метаданные 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'
Вернуться на верх