我们正在通过我们的App Engine应用程序中的云存储JSON API生成可恢复的上传URL,这些API在移动设备和Web应用程序中使用。 在Web应用程序中,使用XmlHttpRequest上传具有可恢复上传URL的文件,我们收到以下错误:
XMLHttpRequest无法加载https://www.googleapis.com/upload/storage/v1beta2/b/ ... No' Access-Control-Allow-Origin'标头出现在请求的资源上。起源' https://ourapp.appspot.com'因此不允许访问。
在Chrome开发者工具中,网络日志会显示第一个OPTIONS请求,其中包含相应的" Origin"请求标题和" Access-Control-Allow-Origin"响应标头但是后面的PUT请求失败了。
我们的桶上的cors xml看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<CorsConfig>
<Cors>
<Origins>
<Origin>*</Origin>
</Origins>
<Methods>
<Method>PUT</Method>
<Method>GET</Method>
<Method>POST</Method>
<Method>HEAD</Method>
<Method>DELETE</Method>
<Method>OPTIONS</Method>
</Methods>
<ResponseHeaders>
<ResponseHeader>*</ResponseHeader>
</ResponseHeaders>
<MaxAgeSec>1800</MaxAgeSec>
</Cors>
</CorsConfig>
欢迎任何建议。
感谢。
答案 0 :(得分:6)
遇到这个问题并发现它是由于来自App Engine的初始POST请求中缺少“origin”标题。
我的POST请求包含content-length(设置为0),x-upload-content-type和origin,一切都很好。
[1] https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload
答案 1 :(得分:3)
我遇到了同样的问题,解决方案是在初始可恢复请求中添加标题Origin: "https://ourapp.appspot.com"
。
但是,由于以下变量,某些图书馆(例如sun.net.www.protocol.http.HttpURLConnection
)不允许您更改Origin
标题:
restrictedHeaders = new String[]{"Access-Control-Request-Headers", "Access-Control-Request-Method", "Connection", "Content-Length", "Content-Transfer-Encoding", "Host", "Keep-Alive", "Origin", "Trailer", "Transfer-Encoding", "Upgrade", "Via"};
我的解决方法是创建一个新的HttpRequest,其中包含一个允许更新Origin
标头的库。我在我的案例中使用了Okhttp(作为以前的Android开发者)。
OkHttpClient client = new OkHttpClient();
AppIdentityService appIdentityService = credential.getAppIdentityService();
Collection<String> scopes = credential.getScopes();
String accessToken = appIdentityService.getAccessToken(scopes).getAccessToken();
Request request = new Request.Builder()
.url("https://www.googleapis.com/upload/storage/v1/b/" + bucket + "/o?name=" + fileName + "&uploadType=resumable")
.post(RequestBody.create(MediaType.parse(mimeType), new byte[0]))
.addHeader("X-Upload-Content-Type", mimeType)
.addHeader("X-Upload-Content-Length", "" + length)
.addHeader("Origin", "https://ourapp.appspot.com")
.addHeader("Origin", "*")
.addHeader("authorization", "Bearer "+accessToken)
.build();
Response response = client.newCall(request).execute();
return response.header("location");
答案 2 :(得分:2)
这是使用JSON API使用可恢复上传的已知问题。我假设&#34;起源&#34;用于启动可恢复上传和&#34;来源&#34;用于上传的数据在你的情况下是不同的,对吗?
这个问题涉及两个部分:
1)使用可恢复上传协议时,&#34;来源&#34;从第一个(开始上传)请求始终用于决定&#34; access-control-allow-origin&#34;响应中的标题,即使您使用不同的&#34;来源&#34;对于后续请求。
2)GCS中的CORS配置仅适用于XML API。我认为我们的文档可以使用一些改进来使其更加清晰,现在它只是这里提到的那种(https://developers.google.com/storage/docs/cross-origin#Sending-a-Cross-Domain_Request)如果你点击链接看看哪些请求URI将响应CORS配置。 JSON API忽略CORS配置,并始终允许&#34;来源&#34;在请求中。
因此,如果您使用带有JSON API的可恢复上传,它将只使用&#34;来源&#34;从第一个请求开始,设置&#34; access-control-allow-origin&#34;标题到那个起源。因此,如果原点在后续上传请求中发生变化,则它们将无效。
目前,您有两种方法可以解决此问题:
1)对第一个和后续请求使用相同的原点。
2)切换到使用XML API,并将CORS配置设置为&lt; Origin&gt; *&lt; / Origin&gt;。
答案 3 :(得分:1)
问题不在于上面显示的CORs文档。如果xhr请求是formdata,可以使用xhr上传文件,如下所述:http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-sending。如果请求不是FormData,我们会收到“Access-Control-Allow_Origin”错误。
这对我有用:
$("input[type=file]").change(function() {
var formData = new FormData();
formData.append("field, ...);
formData.append("field, ...);
formData.append("file", filesList[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', "https://my-bucket.storage.googleapis.com/", true);
xhr.onload = function(e) {
console.log("File Uploaded!")
};
xhr.send(formData);
}
在此处查看完整的node.js示例:https://github.com/sfarthin/crop-rotate-and-sample-in-browser
答案 4 :(得分:-1)
端点https://www.googleapis.com
不允许跨源资源共享(CORS)。这意味着所有浏览器都会阻止从未在源主机(www.googleapis.com)上运行的网站发出请求。
确保为您的存储桶配置了CORS,例如:
<?xml version="1.0" encoding="UTF-8"?>
<CorsConfig>
<Cors>
<Origins>
<Origin>https://ourapp.appspot.com</Origin>
</Origins>
<Methods>
<Method>GET</Method>
<Method>HEAD</Method>
<Method>PUT</Method>
</Methods>
</Cors>
</CorsConfig>
如果仍未设置<Origin>*</Origin>
,请尝试使用curl并报告结果。