收到一个奇怪的错误。
当用户想要上传文件时,他们会向我的服务器发送 AJAX 请求。我的服务器使用 OAuth2 向 Google 的服务器验证服务器端,创建访问令牌,开始断点续传,并将断点续传上传 URI 和访问令牌传递给浏览器。
然后,浏览器直接上传到谷歌存储。
一切似乎都很好。该文件进入存储桶没有问题,但我仍然在 Chrome 上收到 CORS 错误,我不确定在哪里或为什么。这是我的javascript代码的简化版本:
var file = document.getElementById("fileInput").files[0];
var request = requestUpload();
var token = request.token;
var uri = request.uri;
var r = new XMLHttpRequest();
r.open('PUT', uri, true);
r.setRequestHeader("Authorization", "Bearer "+token);
r.send(file);`
很简单 - 但我仍然遇到这个常见错误:
XMLHttpRequest cannot load https://www.googleapis.com/upload/storage/v1/b/*****. No 'Access-Control-Allow-Origin' header is present on the requested resource.
尽管它似乎完全起作用。Javascript 是否请求查看某些默认不允许我查看的内容?我不想有错误。
XMLHttpRequest 对象还会在完成所有上载后触发错误事件。我猜这个请求期待谷歌的某种反馈,但它没有得到,JavaScript正在成为JavaScript的拉丁语,所以我发现的大部分讨论都是关于jQuery的。
非常感谢!
我刚刚遇到了这个确切的问题。 让我挠了挠头,但我想出了一个解决方案。 它的文档很少,并且行为并不完全有意义,但是如果您查看此页面上的最后一个项目符号点
https://cloud.google.com/storage/docs/cross-origin
使用可恢复上传协议时,来自第一个(开始上传(请求的源始终用于确定响应中的访问控制-允许-源标头,即使您对后续请求使用不同的源也是如此。因此,您应该对第一个和后续请求使用相同的源,或者如果第一个请求与后续请求具有不同的源,请使用 CORS 配置设置为 * 的 XML API。
所以我所做的是在来自服务器的可恢复会话启动请求中添加了Origin: http://example.com
请求标头。 这样,与该上传会话 ID 对应的所有客户端请求都将根据该源进行检查。
我仍然觉得奇怪的一件事是浏览器发出的OPTIONS
预检请求(至少对我来说(允许任何内容通过,即使PUT
请求失败。
即使在执行gsutil cors get gs://your-bucket
时使用此配置,您也需要根据@Craig的答案启动初始 POST 请求:
[{"maxAgeSeconds": 3600, "method": ["GET", "PUT", "POST", "HEAD", "DELETE"], "origin": ["*"], "responseHeader": ["*"]}]
.
例如使用 golang 很容易将Origin
传递给 gcloud 请求。有了r http.Request
输入,您可以执行r.Header.Get("Origin")
并将其传递给在gcloud上调用POST的函数。这是我在 golang 中编写的一个函数:
func GetUploadURL(bucket, object, contentType, origin string, expires time.Time) (string, error) {
url, err := storage.SignedURL(bucket, object, &storage.SignedURLOptions{
GoogleAccessID: "your-service-account@your-gcloud-project.iam.gserviceaccount.com",
PrivateKey: pkey, // set this in package init() function
Method: http.MethodPost,
Expires: expires,
ContentType: contentType,
Headers: []string{"x-goog-resumable:start"},
})
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return "", err
}
req.Header.Set("Content-Type", contentType)
req.Header.Set("x-goog-resumable", "start")
req.Header.Set("Origin", origin)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
return resp.Header.Get("Location"), nil
}