Как вы устанавливаете "Content-Type" при сохранении на S3 с использованием django-хранилищ с бэкэндом S3boto?

Я использую django-storages с s3boto как бэкэнд.

У меня есть один ковш с двумя папками - один для static и один для media. Я достигаю этого, используя django-s3-folder-storage.

Помимо сохранения на S3 с использованием модели, я также хочу реализовать функцию resize-resize-and-cache для сохранения файлов на S3. Для этого я напрямую взаимодействую с ведром S3. Код работает, но Content-Type не установлен на S3.

в iPython:

In [2]: from s3_folder_storage.s3 import DefaultStorage

In [3]: s3media = DefaultStorage()

In [4]: s3media
Out[4]: <s3_folder_storage.s3.DefaultStorage at 0x4788780>

Тестируем, что мы обращаемся к правильному ведру - storage_test - это тот, который я создал ранее:

In [5]: s3media.exists('storage_test')
Out[5]: True

In [6]: s3media.open("test.txt", "w")
Out[6]: <S3BotoStorageFile: test.txt>

In [7]: test = s3media.open("test.txt", "w")

In [8]: test
Out[8]: <S3BotoStorageFile: test.txt>

In [9]: test.key.content_type = "text/plain"

In [10]: test.write("...")

In [11]: test.close()

In [12]: test = s3media.open("test.txt", "w")

In [13]: test.key.content_type
Out[13]: 'binary/octet-stream'

Я также пытался вместо In [9] использовать test.key.metadata и test.key.set_metadata. Ни один из них не делает этого.

Как установить правильный Content-Type?

Ответ 1

Если вы просматриваете исходный код в классе S3BotoStorageFile и function write, заголовок обновляется только из двух мест,

  • upload_headers.update(self._storage.headers), где self._storage.headers берется из AWS_HEADERS
  • self._storage.default_acl

И в функции _flush_write_buffer рассматривается только self._storage.headers. Проверьте строку headers = self._storage.headers.copy()

Поэтому обновление test.key.content_type не будет работать.

Вместо test.key.content_type = "text/plain" at In [9]: попробуйте использовать test._storage.headers['Content-Type'] = 'text/plain', он должен работать.

Ответ 2

В соответствии с этим ответом Content-Type не является метаданных, а скорее заголовками, которые вы настроили при загрузке файла.

Ответ 3

Теперь вы можете просто использовать django-storages >= 1.4 и автоматически угадывать типы mime.

Ответ 4

это была БОРЬБА для меня. Это ТОЛЬКО для Boto3, а не для Boto. Если вы хотите установить эти заголовки, вам нужно получить доступ к объекту следующим образом: file_ ссылается на FileField с настройкой хранилища для использования Boto3 из django-хранилищ:

file_.storage.object_parameters = { 'ContentType': 'text/plain' }

ПРИМЕЧАНИЕ. Для заголовков требуется использовать заголовок, поэтому Content-Type = ContentType, Content-Dispostion = ContentDispostion и т.д. Надеюсь, это поможет!