尝试将文件上传到Google云端硬盘时,请继续收到“登录所需”错误

时间:2016-02-27 23:33:36

标签: javascript google-chrome-extension google-drive-api google-chrome-app drive

我正在编写一个Chrome扩展程序,它会截取某些下载内容(目前是.doc和.docx文件),而是将这些文件自动上传到您的Google驱动程序文件夹中。这是我的清单:

{
    // Default manifest crap.
    "manifest_version": 2,
    "name": "App",
    "description": "SpartaHack 2016 application",
    "version": "1.0",
    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    // Content security needed to access gapi script.
    "content_security_policy": "script-src 'self' https://apis.google.com; object-src 'self'",
    // Need to view downloads, and identity for obvious reasons.
    // The other two permissions allow the script to access files that are outside our domain. 
    "permissions": [
        "downloads",
        "identity",
        "http://*/",
        "https://*/"
    ],
    // Gives us the auth information.
    "oauth2": {
        "client_id": "id",
        "scopes": [
            "https://www.googleapis.com/auth/drive.file",
            "https://www.googleapis.com/auth/userinfo.profile"
        ]
    },
    // Scripts that are always running.
    // Client.js has the gapi script, eventPage is our code.
    "background": {
        "scripts": ["client.js", "eventPage.js"]
    }
}

如果需要,我还编写了以下预先授权的方法:

chrome.identity.getAuthToken({
    "interactive": true
}, sendAuthToken);

function sendAuthToken(token) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=' + token, true);
    xhr.onload = function() {
        console.log(xhr.response);
    }

    //TODO: 
    xhr.send();
    console.log(token);
    watchDownloads();
}

我从某个地方的例子中找到了这个片段。它似乎不足以完成授权,但我必须使用此令牌发送对用户信息的请求。这部分没有给我带来任何麻烦 - 令牌记录正常,记录的响应会按预期显示我的所有信息。

以下是watchDownloads()的样子:

function watchDownloads() {
    chrome.downloads.onCreated.addListener(function(download) {
        if(download.url.endsWith(".doc") || download.url.endsWith(".docx")) {
            // Get blob from URL
            var xhr = new XMLHttpRequest();
            xhr.open("GET", download.url, true);
            xhr.responseType = "blob";

            xhr.onload = function(error) {
                if(this.status == 200) {
                    insertFile(this.response, function(resp) {
                        console.log(resp);
                    });
                }
            };

            xhr.send();
        }
    });
}

简而言之,它会查找我关注的两个文件扩展名,如果它看到它们,则应该使用另一个HTTP请求直接将该文件传输到文件的URL,然后将其上传到驱动器中我们使用这种方法,主要是从在线样本拼凑而成:

function insertFile(fileData, callback) {
    const boundary = "-------314159265358979323846";
    const delimiter = "\r\n--" + boundary + "\r\n";
    const close_delimiter = "\r\n--" + boundary + "--";

    //TODO: Remove
    console.log(fileData);

    var reader = new FileReader();
    reader.readAsBinaryString(fileData);
    reader.onload = function(error) {
        var contentType = fileData.type || "application/octet-stream";
        var metadata = {
            // "title": fileData.filename,
            "title": "Potato",
            "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_delimiter;

        //TODO: Remove
        console.log(multipartRequestBody);

        var request = gapi.client.request({
            "path": "/upload/drive/v3/files",
            "method": "POST",
            "params": {
                "key": "key",
                "uploadType": "multipart"
            },
            "headers": {
                "Content-Type": 'multipart/mixed; boundary="' + boundary + '"'
            },
            "body": multipartRequestBody
        });

        //TODO: Remove
        console.log(request);

        if(!callback) {
            callback = function(file) {
                console.log(file)
            };
        }

        request.execute(callback);
    }
}

这是失败的地方。我似乎无法使其正常工作,因为每次都会出现以下错误:

enter image description here

如果要在此处正确登录,我该怎么办?我尝试在标题中添加Authorization属性,但得到相同的错误。

3 个答案:

答案 0 :(得分:1)

Google Drive API(以及其他Google产品)也使用oAuth2.0作为其授权协议。所有要求都将被授权。

可以在documentation中找到授权您的应用使用Drive API的详细步骤。

  1. 创建应用程序时,请使用Google Developers Console进行注册。然后,Google会提供您稍后需要的信息,例如客户端ID和客户端密码。
  2. 在Google Developers Console中激活Drive API。 (如果API未在开发人员控制台中列出,则跳过此步骤。)
  3. 当您的应用需要访问用户数据时,它会要求Google提供特定的访问权限。
  4. Google向用户显示同意屏幕,要求他们授权您的应用程序请求他们的部分数据。
  5. 如果用户批准,那么Google会为您的应用提供一个短期访问令牌。
  6. 您的应用程序请求用户数据,将访问令牌附加到请求。
  7. 如果Google确定您的请求和令牌有效,则会返回请求的数据。
  8. 如果您想要完全访问用户的文件或页面上列出的特定文件,则可以使用https://www.googleapis.com/auth/drive

答案 1 :(得分:1)

这可能有助于其他人绊倒这个问题 如果您确实授权使用JWT,请务必在API调用中加入auth: <your jwtClient>,例如:

首先,获取令牌:

// Configure JWT auth client
var privatekey = require("./<secret>.json")
var jwtClient = new google.auth.JWT(
  privatekey.client_email,
  null,
  privatekey.private_key,
  ['https://www.googleapis.com/auth/drive']
);

// Authenticate request
jwtClient.authorize(function (err, tokens) {
  if (err) {
    return;
  } else {
    console.log("Google autorization complete");
  }
});

然后,调用API (但不要忘记auth:jwtClient部分)

drive.files.create({
    auth: jwtClient,
    resource: {<fileMetadata>},
    fields: 'id'
  }, function (err, file) {
    if (err) {
      // Handle error
    } else {
      // Success is much harder to handle
    }
});

答案 2 :(得分:0)

如果您使用的是Swift:  在viewcontroller的开头添加下一个模块 “导入GTMSessionFetcher”

没有这个库,我将无法使用提取程序授权程序,它是在您安装Pod文件时创建的