使用JavaScript授权Google Drive

我试图授权我的应用程序与Google云端硬盘集成。 Google文档提供了基于服务器的授权和各种服务器技术的代码示例的详细信息

还有一个JavaScript Google API库 ,支持授权。 在维基的示例部分,有一个代码片段用于创buildconfiguration并调用授权function 。 我已经改变了我认为是驱动器所需的范围:

var config = { 'client_id': 'my_client_ID', 'scope': 'https://www.googleapis.com/auth/drive.file' }; gapi.auth.authorize(config, function() { console.log(gapi.auth); }); 

从来没有调用callback函数(是的,谷歌API库被加载更正)。看看Java的取回和使用OAuth 2.0凭据的例子,客户端的秘密似乎是一个参数,如果这进入configuration?

有没有人在JS,Drive或其他Google API上试过这个? 有没有人知道debugging这样一个问题的最佳途径,也就是说,我是否需要一步步走过图书馆,并停止呼啸?

请不要build议在服务器端进行授权,我们的应用程序完全是客户端,我不想在服务器上的任何状态(我理解这将导致令牌刷新问题)。 我熟悉Google控制台中的APIconfiguration,我相信和驱动器SDK设置是正确的。

使用Google云端硬盘可以使用Google API Javascript客户端库,但是您必须知道存在一些问题。

目前有两个主要问题,两个都有工作周期:

授权

首先,如果您仔细观察Google Drivevalidation的工作方式,您将会意识到,在用户安装了您的云端硬盘应用程序并尝试打开文件或使用您的应用程序创build新文件之后,云端硬盘会自动启动OAuth 2.0授权stream程, auth参数设置为response_type = codeaccess_type = offline 。 这基本上意味着现在Drive应用程序被迫使用OAuth 2服务器端stream程,这对于Javascript客户端库(仅使用客户端stream程)没有任何用处。

问题是:Drive启动服务器端OAuth 2.0stream程,然后Javascript客户端库启动客户端OAuth 2.0stream程。

这仍然可以工作,您只需使用服务器端代码来处理在Drive服务器端stream程(您需要交换访问令牌和刷新令牌)后返回的授权代码。 这样,只有在第一个stream程中才会提示用户进行授权。 第一次交换授权码后,auth页面将自动跳过。

服务器端样本可以在我们的文档中find 。

如果您不在服务器端stream程中处理/交换authentication码,每次尝试从云端硬盘使用您的应用程序时,都会提示用户进行authentication。

处理文件内容

第二个问题是上传和访问实际的Drive文件内容并不容易通过我们的Javascript客户端库。 你仍然可以做到这一点,但你将不得不使用自定义的Javascript代码。

读取文件内容

当文件元数据/文件对象被检索时,它包含指向实际文件内容的downloadUrl属性。 现在可以使用CORS请求下载文件,最简单的authvalidation方法是在URL参数中使用OAuth 2访问令牌。 因此,只需将&access_token=...附加到downloadUrl然后使用XHR或通过将用户转发到URL来获取文件。

上传文件内容

更新更新:上传端点现在支持CORS。

~~更新:上传端点,不像其他的Drive API不支持CORS,所以你现在必须使用下面的技巧:~~

上传一个文件是非常棘手的,因为它不是内置在Javascript客户端库中,你不能完全按照这个响应中描述的那样使用HTTP,因为我们不允许在这些API端点上进行跨域请求。 所以你必须利用我们的Javascript客户端库使用的iframe代理,并使用它来发送构build的多部分请求到Drive SDK。 感谢@Alain ,我们有一个如何做到这一点的样本:

 /** * Insert new file. * * @param {File} fileData File object to read data from. * @param {Function} callback Callback function to call when the request is complete. */ function insertFileData(fileData, callback) { const boundary = '-------314159265358979323846'; const delimiter = "\r\n--" + boundary + "\r\n"; const close_delim = "\r\n--" + boundary + "--"; var reader = new FileReader(); reader.readAsBinaryString(fileData); reader.onload = function(e) { var contentType = fileData.type || 'application/octet-stream'; var metadata = { 'title': fileData.fileName, 'mimeType': contentType }; var base64Data = btoa(reader.result); var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + contentType + '\r\n' + 'Content-Transfer-Encoding: base64\r\n' + '\r\n' + base64Data + close_delim; var request = gapi.client.request({ 'path': '/upload/drive/v2/files', 'method': 'POST', 'params': {'uploadType': 'multipart'}, 'headers': { 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' }, 'body': multipartRequestBody}); if (!callback) { callback = function(file) { console.log(file) }; } request.execute(callback); } } 

为了改善这一切,将来我们可能会:

  • 让开发人员select要使用的OAuth 2.0stream(服务器端还是客户端),还是让开发人员完全处理OAuthstream。
  • /upload/...端点上允许CORS
  • 允许exportLinks上的CORS用于本机gDoc
  • 我们应该更容易使用我们的Javascript客户端库上传文件。

没有承诺在这一点虽然:)

我做的。 下面是我的代码:

 <!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <style> p { font-family: Tahoma; } </style> </head> <body> <!--Add a button for the user to click to initiate auth sequence --> <button id="authorize-button" style="visibility: hidden">Authorize</button> <script type="text/javascript"> var clientId = '######'; var apiKey = 'aaaaaaaaaaaaaaaaaaa'; // To enter one or more authentication scopes, refer to the documentation for the API. var scopes = 'https://www.googleapis.com/auth/drive'; // Use a button to handle authentication the first time. function handleClientLoad() { gapi.client.setApiKey(apiKey); window.setTimeout(checkAuth,1); } function checkAuth() { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult); } function handleAuthResult(authResult) { var authorizeButton = document.getElementById('authorize-button'); if (authResult && !authResult.error) { authorizeButton.style.visibility = 'hidden'; makeApiCall(); } else { authorizeButton.style.visibility = ''; authorizeButton.onclick = handleAuthClick; } } function handleAuthClick(event) { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult); return false; } // Load the API and make an API call. Display the results on the screen. function makeApiCall() { gapi.client.load('drive', 'v2', function() { var request = gapi.client.drive.files.list ( {'maxResults': 5 } ); request.execute(function(resp) { for (i=0; i<resp.items.length; i++) { var titulo = resp.items[i].title; var fechaUpd = resp.items[i].modifiedDate; var userUpd = resp.items[i].lastModifyingUserName; var fileInfo = document.createElement('li'); fileInfo.appendChild(document.createTextNode('TITLE: ' + titulo + ' - LAST MODIF: ' + fechaUpd + ' - BY: ' + userUpd )); document.getElementById('content').appendChild(fileInfo); } }); }); } </script> <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script> <p><b>These are 5 files from your GDrive :)</b></p> <div id="content"></div> </body> </html> 

你只需要改变:

  • var clientId ='######';
  • var apiKey ='aaaaaaaaaaaaaaaaaaa';

从您的Google API控制台添加到您的clientID和ApiKey 🙂

当然,您必须在Google API Console上创build项目,激活云端硬盘API并在OAuth 2.0中激活Google帐户身份validation(实际上eeeeasy!)

PS:它不会在你的电脑本地工作,它将在一些托pipe工作,而同时必须在项目控制台提供它的url:)