【问题标题】:No 'Access-Control-Allow-Origin' header with resumable upload没有可恢复上传的“Access-Control-Allow-Origin”标头
【发布时间】:2014-06-08 12:55:45
【问题描述】:

我们正在通过我们的 App Engine 应用程序中的云存储 JSON API 生成可恢复的上传 URL,该应用程序可用于移动设备和网络应用程序。 在 web 应用程序中,使用 XmlHttpRequest 上传带有可恢复上传 url 的文件,我们收到以下错误:

XMLHttpRequest 无法加载 https://www.googleapis.com/upload/storage/v1beta2/b/... 请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 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>

欢迎提出任何建议。

谢谢。

【问题讨论】:

  • 我遇到了同样的问题——CORS 设置正确,并且我对任何其他服务端点都没有问题。你修过吗?
  • @ovangle 不,我们暂时放弃使用上传 URL,我们改用 XML Api
  • 您是否在 PUT 请求中使用了cors query string parameter
  • 我实际上遇到了完全相同的问题。 @akgill 我相信 ?cors 查询字符串用于更改与存储桶关联的 cors 标头。不是为了像我们在这里尝试的那样向存储桶发出可恢复的上传请求。
  • 您不需要在存储桶上设置 CORS。只需在请求可恢复上传 url 时正确设置原点即可。

标签: google-app-engine google-api xmlhttprequest google-cloud-storage


【解决方案1】:

遇到这个问题,发现这是由于来自 App Engine 的初始 POST 请求中缺少“origin”标头。

我的 POST 请求包含内容长度(设置为 0)、x-upload-content-type 和来源,一切正常。

[1]https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload

【讨论】:

  • 我只是想指出,我们有同样的问题,但我们的问题是原始请求在我们的域末尾有一个 /,Google 不接受。所以我们的起源是http://our-domain.com/ 而不是http://our-domain.com。错误是一样的,很难找到。
【解决方案2】:

我遇到了同样的问题,解决方法是在初始可恢复请求中添加一个 Header 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"};

我的解决方法是使用允许更新 Origin 标头的库创建一个新的 HttpRequest。我在我的案例中使用了 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");

【讨论】:

    【解决方案3】:

    这是通过 JSON API 使用可恢复上传的已知问题。我假设用于开始可恢复上传的“原点”和用于上传数据的“原点”在您的情况下是不同的,对吧?

    这个问题涉及到两个部分:

    1) 使用可恢复上传协议时,始终使用来自第一个(开始上传)请求的“来源”来决定响应中的“访问控制允许来源”标头,即使您使用不同的“源”用于后续请求。

    2) GCS 中的 CORS 配置仅适用于 XML API。我认为我们的文档可以使用一些改进来使这一点更清楚,现在它只是在这里提到的(https://developers.google.com/storage/docs/cross-origin#Sending-a-Cross-Domain_Request),如果您单击链接以查看哪些请求 URI 将响应 CORS 配置。 JSON API 会忽略 CORS 配置,并始终允许对请求中的“源”进行跨源访问。

    因此,如果您通过 JSON API 使用可恢复上传,它将仅使用第一个请求中的“来源”,并将“访问控制允许来源”标头设置为该来源。因此,如果后续上传请求中的来源发生变化,它们将无法正常工作。

    目前您有两种方法可以解决此问题:

    1) 对第一个请求和后续请求使用相同的来源。

    2) 切换到使用 XML API,并将 CORS 配置设置为 *

    【讨论】:

    • 因为这个问题,我们最终切换到 AWS。
    • 您好,我们已经尝试使用 XML API 来配置 cors 并初始化可恢复上传,但我们仍然无法获取 access-control-allow-origin 标头。你有更多关于如何解决这个问题的细节吗?谢谢! P.S 我们按照这个文档来实现续传:cloud.google.com/storage/docs/concepts-techniques#resumable
    【解决方案4】:

    问题不在于上面显示的 COR 文档。如果 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

    【讨论】:

    • 我真的无法让它正常工作,即使 chrome 仍然显示相同的错误,它也会上传文件。存储桶上的文件还包含 webkit 表单边界。
    • 你有例子可以看吗?我会在接下来的几天内将一个工作示例推送到 github。
    • 虽然我没有使用 App Engine。刚刚使用 node.js 签名的网址
    • @Jkmn 要将 webkit 表单边界保留在云存储桶上的文件之外,请将其作为 blob 而不是 formdata 上传。示例function doUpload(uri, file){ var blob = new Blob([file], {type: file.type || 'application/octet-stream'}) return $j.ajax({ dataType: 'json', url: uri, data: blob, processData: false, contentType: false, type: 'POST' }); }
    • 这是一个将画布转换为图像并上传到 GCS 的示例:github.com/sfarthin/crop-rotate-and-sample-in-browser/blob/… 对我来说效果很好,希望它有用。
    【解决方案5】:

    端点 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> 
    

    如果它仍然不工作集&lt;Origin&gt;*&lt;/Origin&gt;,请尝试使用 curl 并报告结果。

    【讨论】:

    • 我很确定它与here 所描述的一样,我看到它可以处理 GET 请求。
    • 检查您是否将 PUT 列为存储桶 CORS 配置中方法的一部分。
    • 我已经允许使用 cors 配置中的每个方法的任何来源,但它没有帮助。
    猜你喜欢
    • 2016-09-03
    • 2016-01-21
    • 1970-01-01
    • 2016-08-12
    • 2017-09-19
    • 2015-04-02
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多