Does https://www.googleapis.com/upload/drive/v2/files really support CORS?

后端 未结 3 809
名媛妹妹
名媛妹妹 2020-12-11 22:22

Update: This is a bug in GoogleDrive, CORS is not enabled for upload URIs. @Nivco pointed me to a work around with Google\'s client library which uses an i

相关标签:
3条回答
  • 2020-12-11 22:57

    This answer (and in fact the question itself) is now redundant given full CORS support as confirmed by Steve Bazyl

    Working code, using @Nivco's help, along with detailed explanation:

    Here is the working code for a full test of this technique. To use this, you need to make two pages. The first page authenticates and launches the second page, which is your actual app. In order to be able to access the Google Drive API to upload a file, you need to register an app, which is described here.

    Your first page will use OAuth, which is described in this Stackoverflow answer. It calls your app with a fragment that looks like this:

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

    In JavaScript, you can access that fragment with location.hash. After you save the value, it's a good idea to set location.hash to the empty string right away, so that it doesn't show up in the browser's location bar. Your app needs to use the value of access_token from the fragment in its CORS requests and also in the proxied (non-CORS) request to the upload API. Here is an example launch page, which is really just a version of the code from OAuth example:

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

    Here is an example app that uploads a\na\b\n to a file called leisureUpload in your GoogleDrive, using Google's Client Library for JavaScript. There is no need to use any of the gapi.auth methods, because it uses a raw gapi.client.request() call with the Authorization header directly in the call, just like it would with xmlHttpRequest() using CORS:

    <!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>
    
    0 讨论(0)
  • 2020-12-11 23:19

    It seems that you are right, the upload API endpoints don't seem to support CORS requests whereas the other endpoints do support it (sorry for not having tested thoroughly). This is a bug and we have let our engineering team know about the issue.

    In the mean time it seems that the only workaround is to use the Javascript client library and take advantage of the iframe proxy it uses as described in Authorization of Google Drive using JavaScript

    Thanks for bringing this up!

    0 讨论(0)
  • 2020-12-11 23:21

    CORS is fully enabled now. See https://github.com/googledrive/cors-upload-sample for an example of how to do resumable uploads with vanilla JS.

    0 讨论(0)
提交回复
热议问题