30

IE 10 支持 CORS。Amazon S3 支持 CORS。

我们可以在除 IE 10 之外的所有浏览器中直接从站点到 S3 上传(不打扰 IE 9-)。它是这样工作的:

  1. 用户选择一个文件(拖放或从文件输入中选择)

  2. (POST) 我们必须在请求进入 S3 ( $.post('/static/sign_asset', { ... }) 之前“签署”请求,它有一个全天完美触发的回调。

  3. (POST)然后我们使用文件数据和来自签名等的数据将 XHR 制作为 S3。

var xhr = new XMLHttpRequest();
// ETC
var fd = new FormData();
// ETC
xhr.open('POST', url, true);
xhr.send(fd);

文件上传,一切都在所有浏览器中完美运行,除了......

问题从 IE 10 开始:

  1. 在 Access-Control-Allow-Origin 标头中找不到 Origin null。XMLHttpRequest:网络错误 0x80070005,访问被拒绝。在我们设置response.headers["Access-Control-Allow-Origin"] = "*"发送响应的控制器后,没有其他浏览器显示此内容。即使我们遇到了这个错误,Chrome 也会显示这个错误,但请求仍然会通过。

  2. 尽管出现此错误,该文件实际上确实已上传到 S3。Amazon S3 执行303 重定向操作- 这是我们对文件已成功上传的验证。

  3. (GET) 这是对 CORS Ajax 请求的重定向,因此“重定向”不会刷新页面,它只是返回并访问我们的服务器。IE 10 使用 Content-Type 发出此请求multipart/form-data; boundary=---------------------------7dd2ce2201da

这就是导致 Rails 出错的原因。

Started GET "/static/signed/asset/tsabat/83ee6840-7158-0130-c19b-28cfe912f6ff?bucket=s.cdpn.io&key=5%2Fauthor-tim_2.jpg&etag=%2260fb3876d516553ff6f3a018066b3250%22" for 127.0.0.1 at
 2013-03-17 10:46:36 -0700

EOFError - bad content body:
  (gem) rack-1.4.5/lib/rack/multipart/parser.rb:74:in `block in Rack::Multipart::Parser#fast_forward_to_first_boundary'  (gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#fast_forward_to_first_boundary'
  (gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#parse'
  (gem) rack-1.4.5/lib/rack/multipart/parser.rb:15:in `Rack::Multipart.parse_multipart'
  (gem) rack-1.4.5/lib/rack/multipart.rb:25:in `ActionDispatch::Request#parse_multipart'
  (gem) rack-1.4.5/lib/rack/request.rb:336:in `ActionDispatch::Request#POST'
  (gem) rack-1.4.5/lib/rack/request.rb:201:in `ActionDispatch::Request#POST'

Safari 也失败了(6.0.2)

Safari 返回 200 状态码,Rails 并没有对重定向感到害怕,但 xhr.status 是错误的。xhr.readyState == 4,但 xhr.status == 0。我们一直在寻找 200 以确保它正常工作。这很容易修复,但仍然......

Chrome没问题- 似乎甚至没有设置 Content-Type

Firefox 做得很好- 内容类型application/json; charset=utf-8


有一些示例页面显示了 IE 10 处理 CORS 的能力,但它们不处理这个重定向问题。

4

1 回答 1

10

CodePen 团队成员在这里。我们想通了……

我们希望依赖于 S3 的 POST 功能中内置的 303 重定向,但事实证明这是有问题的,如上所示。相反,我们只是停止使用S3 表单字段 success_action_redirect并切换到success_action_status.

对于后代,不要依赖 S3 的 303 重定向来跨浏览器一致地处理 xhr 请求。如果这样做,您将花费时间与无效标题、空起源和龙作斗争。

于 2013-03-18T03:07:18.420 回答