【问题标题】:How do you set "Content-Type" when saving to S3 using django-storages with S3boto backend?使用带有 S3boto 后端的 django-storages 保存到 S3 时如何设置“Content-Type”?
【发布时间】:2013-06-05 20:44:27
【问题描述】:

我使用django-storagess3boto 作为后端。

我有一个带有两个文件夹的存储桶——一个用于static,一个用于media。我使用django-s3-folder-storage 实现了这一点。

除了使用模型保存到 S3 之外,我还想实现一个图像调整大小和缓存功能来将文件保存到 S3。为此,我直接与我的 S3 存储桶进行交互。该代码有效,但未在 S3 上设置 Content-Type

在 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'

我也尝试过使用test.key.metadatatest.key.set_metadata 来代替In [9]。他们都没有这样做。

如何设置正确的 Content-Type?

【问题讨论】:

    标签: django amazon-s3 boto django-storage


    【解决方案1】:

    如果您查看类 S3BotoStorageFile 和函数 write 中的源代码,则标题仅从 2 个位置更新,

    1. upload_headers.update(self._storage.headers) 其中self._storage.headers 取自AWS_HEADERS
    2. self._storage.default_acl

    并且在函数_flush_write_buffer 中只考虑self._storage.headers。检查headers = self._storage.headers.copy()这一行

    所以更新test.key.content_type 将不起作用。

    尝试使用test._storage.headers['Content-Type'] = 'text/plain',而不是test.key.content_type = "text/plain" In [9]:,它应该可以工作。

    【讨论】:

      【解决方案2】:

      这仅适用于 Boto3,不适用于 Boto。如果您想设置这些标头,则需要像这样访问对象,file_ 引用具有存储设置的 FileField 以使用来自 django-storages 的 Boto3:

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

      注意:它要求标题名称为驼峰式,因此 Content-Type = ContentTypeContent-Dispostion = ContentDispostion 等。希望这会有所帮助!

      【讨论】:

      • 谨慎使用此解决方案,因为storage.object_parameters 是持久的,也就是说,之后将为每个文件/对象设置相同的ContentType。我想更好的方法是将S3Boto3Storage.get_object_parameters 覆盖为documented
      【解决方案3】:

      根据this answer,Content-Type 不是元数据,而是您在上传文件时设置的标头。

      【讨论】:

        【解决方案4】:

        现在您可以使用django-storages &gt;= 1.4,它会自动猜测 mime 类型。

        【讨论】:

        • 自动如何?它使用 mimetypes 库吗?
        • @ryan28561 貌似使用了Python内置的mimetypes模块docs.python.org/3/library/mimetypes.html
        • 谢谢,当我问这个问题时,我正在深入寻找一个将我的 png 设置为 image/apng 的错误。原来 django 在上传后使用 PIL 获取 mimetype,并且 Pillow 5.4.0 中存在错误。
        猜你喜欢
        • 2014-02-02
        • 2015-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-27
        • 1970-01-01
        相关资源
        最近更新 更多