带有django存储的ImageField可以:“分析X-Amz-Credential参数时出错;'美国-东-1'地区是错误的;期待“美国西部1号”“

lsmepo6l  于 2023-02-10  发布在  Go
关注(0)|答案(3)|浏览(215)

我正在尝试将ImageField添加到名为LucyGuide的模型中,该模型将使用django-storages将用户上传的图像保存到S3。

class LucyGuide(TimeStampedModel):
    headshot = models.ImageField(upload_to='uploads/', null=True)
    bio = models.TextField(blank=True)

我在settings.py中添加了以下内容:

# Use Boto3 backend to interact with Amazon's S3
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# Amazon S3 credentials (for django-storages)
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', default='')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY', default='')

AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME', default='')
AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME')
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}
# Use v4 of the signing protocol (recommended for all new projects)
AWS_S3_SIGNATURE_VERSION = 's3v4'

其中从.env文件读取实际密钥(使用类似于django-decouple的机制)。
为了尝试一下,我在Django的管理界面上传了一张LucyGuide的随机图片:

在shell中,我可以访问指南的headshot字段的url属性,它实际上是一个到AWS bucket的链接:

In [6]: guide = LucyGuide.objects.filter(bio__startswith="Kristen").first()

In [7]: guide
Out[7]: <LucyGuide: Kristen Hoover>

In [8]: guide.headshot
Out[8]: <ImageFieldFile: uploads/320px-Waaah.jpg>

In [9]: guide.headshot.url
Out[9]: 'https://lucy-prod.s3.amazonaws.com/uploads/320px-Waaah.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIMC2A%2F20180327%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180327T200248Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=ae75dbdd75d13020113c12ef2d655e3'

(我已经删除了部分URL).问题是当我尝试在浏览器中访问此URL时,出现"This XML file does appeared to have any style information associated with it"错误:

<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>
Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'us-west-1'
</Message>
<Region>us-west-1</Region>
<RequestId>1E053D94011E400F</RequestId>
<HostId>
jbkRHVj2y6ygppTsAo2+uOXgby0ok0mbsFsRogKqbu9jPMb+9eGe24nJv441vip3WpmwpFqlsYg=
</HostId>
</Error>

我已经尝试过通过添加AWS_S3_REGION_NAME设置来解决这个问题(参见http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html)。错误消息所指示的区域us-west-1似乎是正确的,因为桶设置在"US West(N. California)":

总而言之,我不明白为什么设置了正确的AWS_S3_REGION_NAME后仍会出现此错误。我该如何修复此错误?

    • 更新**

如果我检查桶中的对象,我会发现它有一个"Link",它比headshot字段的url属性生成的链接简单得多:

我想把这里显示的"基URL"硬编码到我试图构建的检索图像URL的API端点中,但这似乎不是一个优雅的解决方案。

6tr1vspr

6tr1vspr1#

你可以简单地使用AWS_S3_REGION_NAME = 'us-east-2' # replace us-east-2 with your region来代替关闭querystring,这样更安全。

vuktfyat

vuktfyat2#

通过阅读django-storages源代码(并在其中设置断点),我能够通过添加设置来解决这个问题

AWS_QUERYSTRING_AUTH = False

这会更改它的默认值True。现在,url属性会生成一个不带身份验证查询字符串的URL:

In [2]: guide = LucyGuide.objects.filter(bio__startswith='Darrell').first()

In [3]: guide.headshot
Out[3]: <ImageFieldFile: uploads/Waaah.jpg>

In [4]: guide.headshot.url
Out[4]: 'https://lucy-prod.s3.amazonaws.com/uploads/Waaah.jpg'
izj3ouym

izj3ouym3#

您需要将变量AWS_S3_REGION_NAME添加到settings.py。您的env文件中可能缺少该变量。另请参阅:https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

相关问题