我使用XMLHttpRequest发送到服务器端创建的可恢复上载url,将基于浏览器的可恢复上载实施到Google Cloud Storage中。在禁用Web安全性时,这种做法完全正常,这是我在开发过程中所做的。XMLHttpRequest CORS到Google Cloud Storage仅适用于预检请求
但是现在在现实世界中,CORS一直在制造麻烦。我也尝试过使用其他浏览器(没有成功),但是坚持使用chrome进行进一步测试。
注意:在/etc/HOSTS
中的fake.host
条目用于诱骗铬以避免本地主机限制。尽管如此,我们的在线测试服务器的“真实”域也是如此。
请求是使用普通的XMLHttpRequest调用开始:
var xhr = this.newXMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('Content-Type', this.currentInputFile.type);
xhr.setRequestHeader('Content-Range', 'bytes ' + startByte + '-' + (this.currentInputFile.size - 1) + '/' + this.currentInputFile.size);
xhr.onload = function(e) {
...
};
...
if (startByte > 0) {
xhr.send(this.currentInputFile.slice(startByte));
} else {
xhr.send(this.currentInputFile);
}
浏览器然后成功启动预检要求:
Remote Address:173.194.71.95:443
Request URL:https://www.googleapis.com/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
Request Method:OPTIONS
Status Code:200 OK
请求报头:
:host:www.googleapis.com
:method:OPTIONS
:path:/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
:scheme:https
:version:HTTP/1.1
accept:*/*
accept-encoding:gzip,deflate
accept-language:en-US,en;q=0.8,de;q=0.6
access-control-request-headers:content-range, content-type
access-control-request-method:PUT
origin:https://fake.host
referer:https://fake.host/upload.xhtml
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36
x-client-data:YYYYYY
查询字符串参数
uploadType:resumable
name:aa spacetestSMALL_512kb.mp4
upload_id:XXXXXXXXX
响应头
access-control-allow-credentials:true
access-control-allow-headers:content-range, content-type
access-control-allow-methods:PUT
access-control-allow-origin:https://fake.host
alternate-protocol:443:quic
content-length:0
content-type:text/html; charset=UTF-8
date:Fri, 05 Sep 2014 14:11:21 GMT
server:UploadServer ("Built on Aug 18 2014 11:58:36 (1408388316)")
status:200 OK
version:HTTP/1.1
...,直到所有的数据传送开始PUT请求。但是之后,chrome在没有完成/结束请求的情况下悄悄地记录错误:
XMLHttpRequest无法加载https://www.googleapis.com/upload/storage/v1/b/my-bucket-name ... XXXXXXXX。请求的资源上没有“Access-Control-Allow-Origin”标题。因此不允许访问原产地'https://fake.host'。
这是关于什么的PUT请求铬日志:
Request URL:https://www.googleapis.com/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
请求头
Provisional headers are shown
Content-Range:bytes 0-3355302/3355303
Content-Type:video/mp4
Origin:https://fake.host
Referer:https://fake.host/upload.xhtml
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id:YYYYYYY
查询字符串
uploadType:resumable
name:aa spacetestSMALL_512kb.mp4
upload_id:XXXXXXXXX
值得注意的是,在http://client.cors-api.appspot.com/client添加相同的URL时,与发行任何请求,除OPTIONS
请求类型之外的所有请求都会失败。看起来云存储api只会为OPTION请求发出正确的响应头,但不会发出PUT/POST/GET/...请求。
那么我在做一些不可能的事情吗?有什么东西坏了吗?这是云存储API中的错误吗?我花了数小时搜索和阅读SO答案,至今没有任何运气。现在,我可以定期检查下载是否传输了100%的数据,并忽略了http请求结果,因为该文件实际上已完全上传到存储分区。但这是一个相当丑陋的解决方法,如果真正的问题可以解决,我真的不想使用它。
你在GCS上的CORS上设置了吗? https://cloud.google.com/storage/docs/cross-origin#Configuring-CORS-on-a-Bucket – Ryan 2014-10-09 21:07:34
当然可以。我猜没有它,预检请求会失败,而没有。上传文件后只有最终响应无效。 – Roben 2014-10-10 13:10:35
你可以显示你使用的json吗?感觉像你忘记了“方法”:[“PUT”,“POST”,“GET”], – Ryan 2014-10-10 16:00:42