使用CORS的跨域分块上传

fea*_*age 5 nginx xmlhttprequest cross-domain cors fileapi

我有用户提交的文件,我试图以10 MB的块上传.我目前正在使用原始XMLHttpRequest(和XDomainRequest)来推送File.prototoype.slice前端的每个切片().后端是使用上传模块的 Nginx .

仅供参考,以下是我如何使用的概要slice:

element.files[0].slice(...)
Run Code Online (Sandbox Code Playgroud)

据我所知,跨浏览器的前缀的方法webkitSlice,并mozSlice和所有.

我遇到的问题是实际发出跨域请求.我是从上传server.localupload.server.local.在Firefox中,options请求通过正常,然后实际post失败.在Chrome和Opera中,options请求失败

 OPTIONS https://URL Resource failed to load
Run Code Online (Sandbox Code Playgroud)

以下是Firefox的标题:

请求标题

OPTIONS /path/to/asset HTTP/1.1
Host: upload.server.local:8443
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: https://server.local:8443
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-disposition,content-type,x-content-range,x-session-id
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Run Code Online (Sandbox Code Playgroud)

响应标题

HTTP/1.1 204 No Content
Server: nginx/1.2.6
Date: Wed, 13 Feb 2013 03:27:44 GMT
Connection: keep-alive
access-control-allow-origin: https://server.local:8443
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: x-content-range, origin, content-disposition, x-session-id, content-type, cache-control, pragma, referrer, host
access-control-allow-credentials: true
Access-Control-Max-Age: 10000
Run Code Online (Sandbox Code Playgroud)

实际post请求永远不会离开浏览器.Nginx访问日志永远不会看到post.浏览器出于某种原因暂停了它.如何解开为什么这篇文章被阻止?

Chromium 24
Firefox 18
Opera 12.14
Run Code Online (Sandbox Code Playgroud)

我已经核实了所有浏览器都支持CORS正确这里.

通过指向我的上传https://cors-test.appspot.com/test,我已经确认问题肯定是服务器端标题.

Old*_*Pro 1

如果预检未返回足够的权限,则 POST 不会离开浏览器,因此 POST 请求未得到完全授权。问题中包含的请求/响应对我来说确实足够了。

  • 您确定withCredentials = true在 XMLHttpRequest 中进行了设置吗?
  • 您确定您的服务器上有有效的(非自签名的)SSL 证书吗?即使您添加了使用无效证书浏览站点的例外,HTTPS 也可能无法通过 CORS 检查。
  • 您是否尝试过清空缓存?您已Access-Control-Max-Age: 10000在响应标头中设置。也就是接近3个小时。我知道您在这方面的工作时间比这更长,但在特别测试时,请将标头设置为零,这样您就不会因浏览器缓存旧访问权限而疯狂。

一般来说,我会从尽可能宽松地使用 CORS 标头开始,然后慢慢提高安全性以查看哪里失败。然而,这并不完全简单。例如,根据MDN 关于 CORS 的文档

当响应凭证请求时,服务器必须指定域,并且不能使用通配符。如果标头使用通配符,则上面的示例将失败:Access-Control-Allow-Origin: *

当我将您问题的请求部分发送至 时https://cors-test.appspot.com/test,我得到以下信息:

HTTP/1.1 200 OK
Cache-Control: no-cache
Access-Control-Allow-Origin: https://server.local:8443
Access-Control-Allow-Headers: content-disposition,content-type,x-content-range,x-session-id
Access-Control-Allow-Methods: POST
Access-Control-Max-Age: 0
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 35
Vary: Accept-Encoding
Date: Thu, 23 May 2013 06:37:34 GMT
Server: Google Frontend
Run Code Online (Sandbox Code Playgroud)

因此,您可以从那里开始,增加越来越多的安全性,直到它崩溃为止,找出罪魁祸首。