【问题标题】:Does https://www.googleapis.com/upload/drive/v2/files really support CORS?https://www.googleapis.com/upload/drive/v2/files 真的支持 CORS 吗?
【发布时间】:2012-07-21 23:11:16
【问题描述】:

更新:这是 GoogleDrive 中的一个错误,没有为上传 URI 启用 CORS。 @Nivco 向我指出了使用 iframe 和代理(不是 CORS)的 Google 客户端库的解决方法。我将(经过测试的)工作代码放在底部,并附有详细说明。请参阅下面的示例。

Inserting File to Google Drive through APIAuthorization of Google Drive using JavaScript 说上传端点支持 CORS,但我无法使用它们。我可以使用Files: insert 获得授权并插入一个空文件,但我无法将内容上传到其中——当我使用https://www.googleapis.com/upload/drive/v2/files 时出现405(不允许的方法)错误,当我使用这两种技术中的任何一种时在插入文件堆栈溢出帖子中的示例中给出。

CORS 是否可能适用于 v1 而尚未启用 v2?

编辑:顺便说一句,405 错误出现在 chrome 正在发出的 OPTIONS 请求中。

编辑:这是我的一次尝试中的代码:

在展示代码之前,我想强调一下我能够验证和列出文件。我就是无法将数据上传到文件中。

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart');
xhr.setRequestHeader('Authorization', 'Bearer ' + params.access_token);
xhr.setRequestHeader("Content-Type",  'multipart/related; boundary="END_OF_PART"');
xhr.onreadystatechange = function(data) {
  if (xhr.readyState == DONE) {
    document.getElementById("files").innerHTML = "Uploaded file: " + xhr.responseText;
    };
  }
xhr.send([
  mimePart("END_OF_PART", "application/json", json),
  mimePart("END_OF_PART", "text/plain", "a\nb\n"),
  "\r\n--END_OF_PART--\r\n",
].join(''));
function mimePart(boundary, mimeType, content) {
  return [
    "\r\n--", boundary, "\r\n",
    "Content-Type: ", mimeType, "\r\n",
    "Content-Length: ", content.length, "\r\n",
    "\r\n",
    content,
  ].join('');
}

这是请求:

Request URL:https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
Request Method:OPTIONS

回复如下:

Status Code:405 Method Not Allowed
cache-control:no-cache, no-store, must-revalidate
content-length:0
content-type:text/html; charset=UTF-8
date:Mon, 23 Jul 2012 22:41:29 GMT
expires:Fri, 01 Jan 1990 00:00:00 GMT
pragma:no-cache
server:HTTP Upload Server Built on Jul 17 2012 16:15:04 (1342566904)
status:405 Method Not Allowed
version:HTTP/1.1

没有响应,因为 Chrome 收到该 OPTIONS 请求的 405 错误。没有 POST,因为 Chrome 无法继续,因为它的 OPTIONS 请求失败并返回 405,因此它在控制台中打印此错误:

XMLHttpRequest cannot load https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart. Origin https://leisurestorage.appspot.com is not allowed by Access-Control-Allow-Origin.

【问题讨论】:

  • 您使用的是特定浏览器吗?我尝试使用 Chrome,它对我来说非常有效。你看过google-apis-javascript-client项目页面吗?
  • 我已经尝试过 Chrome 和 Firefox。我正在编辑我的原件以添加更多信息。
  • 我添加了更多信息。我可以使用该技术进行身份验证并获取文件列表,但无法使用它将数据上传到文件。
  • 欢迎来到 Stack Overflow,Bill Burdick。感谢您报告解决方案和问题。如果您将其发布为答案,而不是将其附加到您的问题中,那就更好了。
  • 我没想到 - 我将其粘贴为另一个答案

标签: google-drive-api cors


【解决方案1】:

看来您是对的,上传 API 端点似乎不支持 CORS 请求,而其他端点确实支持它(抱歉没有彻底测试)。这是一个错误,我们已经让我们的工程团队知道了这个问题。

与此同时,似乎唯一的解决方法是使用 Javascript 客户端库并利用它使用的 iframe 代理,如 Authorization of Google Drive using JavaScript 中所述

感谢您提出这个问题!

【讨论】:

  • 谢谢!我会试试的。我打算尝试 [developer.yahoo.com/yql/](YQL) 作为上传 API 的替代方式——我认为它使用了类似的方法(通过服务器代理)。 YQL 不起作用有什么原因吗?
  • 糟糕,链接语法倒退了 :) 应该是 YQL
  • 谢谢,@Nivco!我使用您指向我的客户端库让它工作,并用工作代码更新了帖子。
  • 对不起@Nivco - 我添加了一个非常详细的答案并将接受的答案更改为那个答案,即使我早些时候选择了你的答案,并且我得到了 -2。不是有意对你无礼。
【解决方案2】:

CORS 现已完全启用。有关如何使用 vanilla JS 进行可恢复上传的示例,请参阅 https://github.com/googledrive/cors-upload-sample

【讨论】:

    【解决方案3】:

    这个答案(实际上是问题本身)现在是多余的,因为 Steve Bazyl 证实了完全的 CORS 支持

    工作代码,使用@Nivco 的帮助,以及详细解释:

    这是对这项技术进行全面测试的工作代码。要使用它,您需要制作两个页面。第一个页面验证并启动第二个页面,这是您的实际应用程序。为了能够访问 Google Drive API 上传文件,您需要注册一个应用程序,描述为here

    您的第一页将使用 OAuth,在 this Stackoverflow answer 中进行了描述。它使用如下所示的片段调用您的应用:

    #access_token=ya29.AHES6ZSb4M4ju8U_X_zgFrz_MD2RsjrQu5V05HjsBtrCl0nh2SrnaA&token_type=Bearer&expires_in=3600
    

    在 JavaScript 中,您可以使用 location.hash 访问该片段。保存该值后,最好立即将location.hash 设置为空字符串,这样它就不会显示在浏览器的位置栏中。您的应用程序需要在其 CORS 请求以及对上传 API 的代理(非 CORS)请求中使用片段中的 access_token 值。这是一个示例启动页面,它实际上只是 OAuth 示例代码的一个版本:

    <html>
      <body>
        <a href="javascript:poptastic('https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file&client_id=270759921607.apps.googleusercontent.com&redirect_uri=https://leisurestorage.appspot.com&response_type=token');">Authorize Leisure Storage</a><br>
        <script>
          function poptastic(url) {
            var newWindow = window.open(url, 'name', 'height=600,width=450');
            if (window.focus) {
              newWindow.focus();
            }
          }
        </script>
      </body>
    </html>
    

    这是一个示例应用程序,它使用 Google 的 JavaScript 客户端库将 a\na\b\n 上传到您的 GoogleDrive 中名为 leisureUpload 的文件中。不需要使用任何 gapi.auth 方法,因为它直接在调用中使用带有 Authorization 标头的原始 gapi.client.request() 调用,就像使用 CORS 使用 xmlHttpRequest() 一样:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <title>Leisure</title>
        <script type="text/javascript">
        var hash = location.hash.substring(1).split('&');
        location.hash = '';
        var params = {};
    
        for (var i = 0; i < hash.length; i++) {
            var p = hash[i].split('=');
    
            params[p[0]] = p[1];
        }
        function gapiClientLoaded() {/* do nothing */}
        function uploadTestFile() {
            var json = JSON.stringify({
                mimeType: 'text/plain',
                title: 'leisureUpload',
            });
            var xhr = new XMLHttpRequest();
    
            gapi.client.request({
                'path': '/upload/drive/v1/files',
                'method': 'POST',
                'params': {'uploadType': 'multipart'},
                'headers': {
                    'Content-Type': 'multipart/mixed; boundary="END_OF_PART"',
                    'Authorization': 'Bearer ' + params.access_token,
                },
                'body': [
                    mimePart("END_OF_PART", "application/json", json),
                    mimePart("END_OF_PART", "text/plain", "a\nb\n"),
                    "\r\n--END_OF_PART--\r\n",
                ].join('')
            }).execute(function(file) {
                document.getElementById("result").innerHTML = "Uploaded file: " + file;
            });
        }
        function mimePart(boundary, mimeType, content) {
            return [
                "\r\n--", boundary, "\r\n",
                "Content-Type: ", mimeType, "\r\n",
                "Content-Length: ", content.length, "\r\n",
                "\r\n",
                content,
            ].join('');
        }
        </script>
        <script src="https://apis.google.com/js/client.js?onload=gapiClientLoaded"></script>
      </head>
      <body>
        <h1>Welcome to Leisure!</h1>
        <button onclick="uploadTestFile()">Upload Test File</button><br>
        <pre id="result"></pre>
      </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-01
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      相关资源
      最近更新 更多