我们的应用程序最近切换到通过 Rails Active Storage 直接上传到 S3(在 Rails 5.2 中引入) 在大多数情况下,它工作正常,但我们注意到大约 2% 的时间会抛出错误。
到目前为止,我们已经看到了以下内容:
Status 0(主要用于 Safari/Mobile Safari):
Error storing "File_1.jpeg". Status: 0
状态 403:
Error storing "File_1.jpeg". Status: 403
错误阅读:
Error reading "File_1.jpeg".
我想最后一个错误与文件本身无效或损坏有关。 但是,我们不确定是什么导致了前两个错误。 四处搜索,我注意到提到 CORS 设置不正确的帖子。但是,我们之前在 S3 上进行了一些配置更改,我也认为如果这是一个 CORS 问题,我们会更频繁地看到失败。 这就是我们的 CORS 设置:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>https://app.ourapp.com</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3600</MaxAgeSeconds>
<AllowedHeader>Origin</AllowedHeader>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>Content-MD5</AllowedHeader>
<AllowedHeader>Content-Disposition</AllowedHeader>
</CORSRule>
</CORSConfiguration>
我们注意到在一次多次上传中,用户能够将 12 个文件成功上传到活动存储,但有 1 个文件出错,状态为 0。文件本身没有损坏或任何东西。
有什么线索有时会导致直接上传不稳定?
以下对我有用:
[
{
"AllowedHeaders": [
"Authorization"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"https://example.com"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
},
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT"
],
"AllowedOrigins": [
"https://example.com"
],
"ExposeHeaders": []
}
]
从这里.
存储“File_1.jpeg”时出错。状态:0
我已经看到当有数据丢失防护 (DLP) 工具到位时,我们的用户会发生此错误,该工具可防止敏感文件离开他们的网络。如果可能,让用户的 IT 团队检查他们的配置以允许上传此类文件。
我花了 7 个小时来解决这个问题。
什么不是:
关键见解:这只发生在(对我而言)编辑视图上,它应该提交一个
PATCH
,但是当一个文件被提交到表单时,它正在制作一个POST
.
那是一个重要的突破,谷歌搜索让我想到了很多想法。 仔细查看表单提交时的 HTTP 动词;如果它是一个
POST
,而它应该是一个PATCH
,那就是从哪里开始寻找。
我现在需要找出如何让表单理解它需要在提交新的 ActiveStorage 附件时进行修补。
我改了这个
<%= form.label :images %>
<%= form.file_field :images, multiple: true, direct_upload: true %>
到这个
<%= form.label :images %>
<%= form.file_field :images, multiple: true %>
突然间一切都奏效了。我完全不知道为什么!我从这里得到了这个想法。
调试提示:如果这个问题只发生在生产中,请尝试通过跳转到
config/environments/development.rb
并设置config.active_storage.service = :amazon
来在本地模拟它(然后您可以在本地测试以便更容易看到日志),请小心,因为它可能将 blob 发送到您的生产 S3(我的是一个新应用程序,所以我可以随意发送文件)。
复习:如果变量是新的,
_form.html.erb
partial 通常会提交 POST,否则会提交 PATCH。 (见这里)。
我在我正在设置的应用程序上看到了这一点(与 OP 问题不同,这是持续的,不是间歇性的)。
我观察到存储“xxxx”时出错。状态:0 当其中任何一个为真时:
• 没有在我的
config/storage.yml
文件中配置“桶”设置。
• 没有为正确的主机配置 CORS 时
我观察到存储“xxxx”时出错。状态:400 时间:
• 我为 AWS 配置了错误的区域(但存储桶名称正确)