3

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

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

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.
4

3 回答 3

2

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

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

感谢您提出这个问题!

于 2012-07-24T00:03:49.280 回答
2

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

于 2013-09-23T19:32:11.703 回答
0

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

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

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

您的第一页将使用 OAuth,此 Stackoverflow 答案中对此进行了描述。它使用如下所示的片段调用您的应用程序:

#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>
于 2012-07-25T20:06:32.803 回答