javascript - 从node.js googledrive api返回结果

标签 javascript node.js oauth-2.0 google-drive-api

我有一个在 Node.js 服务器上使用 Google Drive API 将文件上传到 Google Drive 的流程。 一切正常,文件已上传到我的谷歌驱动器内的特定文件夹。 我创建了一个包含所有功能的文件 google-drive.js

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');

// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/drive'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';


function readFile(filePath) {
  fs.readFile('./server/drive/credentials.json', (err, content) => {
    if (err) return console.log('Error loading client secret file:', err);
    // Authorize a client with credentials, then call the Google Drive API.
    // return authorize(JSON.parse(content), listFiles);
     authorize(JSON.parse(content), filePath, uploadFile);
  })
}

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, filePath, callback) {
  const {client_secret, client_id, redirect_uris} = credentials.web;
  const oAuth2Client = new google.auth.OAuth2(
    client_id, client_secret, redirect_uris[0]);

  // Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getAccessToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client, filePath);
  });
}

/**
 * Get and store new token after prompting for user authorization, and then
 * execute the given callback with the authorized OAuth2 client.
 * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
 * @param {getEventsCallback} callback The callback for the authorized client.
 */
function getAccessToken(oAuth2Client, callback) {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
  });
  console.log('Authorize this app by visiting this url:', authUrl);
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question('Enter the code from that page here: ', (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
      if (err) return console.error('Error retrieving access token', err);
      oAuth2Client.setCredentials(token);
      // Store the token to disk for later program executions
      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
        if (err) return console.error(err);
        console.log('Token stored to', TOKEN_PATH);
      });
      callback(oAuth2Client, filePath);
    });
  });
}

/**
 * Lists the names and IDs of up to 10 files.
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */
function listFiles(auth) {
  const drive = google.drive({version: 'v3', auth});
  drive.files.list({
    pageSize: 10,
    fields: 'nextPageToken, files(id, name)',
  }, (err, res) => {
    if (err) return console.log('The API returned an error: ' + err);
    const files = res.data.files;
    if (files.length) {
      console.log('Files:');
      files.map((file) => {
        console.log(`${file.name} (${file.id})`);
      });
    } else {
      console.log('No files found.');
    }
  });
}

function uploadFile(auth, filePath) {
  const drive = google.drive({version: 'v3', auth});
  const folderMetaData = {
    'name': 'TEST_FOLDER',
    'mimeType': 'application/vnd.google-apps.folder'
  };
  return drive.files.create({
    resource: folderMetaData,
    fields: 'id'
  }, function (err, file) {
    if (err) {
      console.log(err);
      return err;
    } else {
      const folderId = file.data.id;
      const fileMetadata = {
        'name': 'TEST_IMAGE',
        parents: [folderId]
      };
      const media = {
        mimeType: 'image/jpeg',
        body: fs.createReadStream(filePath)
      };
      drive.files.create({
        resource: fileMetadata,
        media: media,
        fields: 'id'
      }, (err, file) => {
        if (err) {
          // Handle error
          return err;
        } else {
          return file;
        }
      });
    }
  })

}

module.exports = {
  // Load client secrets from a local file.
  read: function (filePath) {
    return readFile(filePath);
  }
};

在我的 server.js (主文件)中,我导入了 google-drive.js 并添加了如下路由:

app.post('/api/drive/auth', async (req, res) => {
  let result = null;
  result = await drive.read(req.body.filePath);
  console.log(result)
  res.status(200).json('success');
});

问题是,我似乎无法从上传流程中获得结果,每次我 console.log(result) 时,我都会得到 undefined

最佳答案

我想提出以下修改。

修改点:

  • 在 Node.js 的 googleapis 中,drive.files.listdrive.files.create 返回 Promise。

当这一点反射(reflect)到您的脚本中时,它会变成如下所示。

修改后的脚本:

const fs = require("fs");
const readline = require("readline");
const { google } = require("googleapis");

// If modifying these scopes, delete token.json.
const SCOPES = ["https://www.googleapis.com/auth/drive"];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';

function readFile(filePath) {
  return new Promise((resolve) => {
    fs.readFile('./server/drive/credentials.json', (err, content) => {
      if (err) return console.log("Error loading client secret file:", err);
      // Authorize a client with credentials, then call the Google Drive API.
      // authorize(JSON.parse(content), (auth) => resolve(listFiles(auth))); // <--- Modified. When you use "listFiles", please use this line.
      authorize(JSON.parse(content), (auth) => resolve(uploadFile(auth, filePath))); // <--- Modified
    });
  });
}

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, callback) {
  // const { client_secret, client_id, redirect_uris } = credentials.web;
  const { client_secret, client_id, redirect_uris } = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(
    client_id,
    client_secret,
    redirect_uris[0]
  );

  // Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getAccessToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client); // <--- Modified
  });
}

/**
 * Get and store new token after prompting for user authorization, and then
 * execute the given callback with the authorized OAuth2 client.
 * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
 * @param {getEventsCallback} callback The callback for the authorized client.
 */
function getAccessToken(oAuth2Client, callback) {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: "offline",
    scope: SCOPES,
  });
  console.log("Authorize this app by visiting this url:", authUrl);
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question("Enter the code from that page here: ", (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
      if (err) return console.error("Error retrieving access token", err);
      oAuth2Client.setCredentials(token);
      // Store the token to disk for later program executions
      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
        if (err) return console.error(err);
        console.log("Token stored to", TOKEN_PATH);
      });
      callback(oAuth2Client); // <--- Modified
    });
  });
}

/**
 * Lists the names and IDs of up to 10 files.
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */
async function listFiles(auth) {  // <--- Modified
  const drive = google.drive({ version: "v3", auth });
  const res = await drive.files
    .list({
      pageSize: 10,
      fields: "nextPageToken, files(id, name)",
    })
    .catch(console.log);
  return res;  // or return res.data;
}

async function uploadFile(auth, filePath) {  // <--- Modified
  const drive = google.drive({ version: "v3", auth });
  const folderMetaData = {
    name: "TEST_FOLDER",
    mimeType: "application/vnd.google-apps.folder",
  };
  const res1 = await drive.files
    .create({
      resource: folderMetaData,
      fields: "id",
    })
    .catch(console.log);
  const folderId = res1.data.id;
  const fileMetadata = {
    name: "TEST_IMAGE",
    parents: [folderId],
  };
  const media = {
    mimeType: 'image/jpeg',
    body: fs.createReadStream(filePath),
  };
  const res2 = await drive.files
    .create({
      resource: fileMetadata,
      media: media,
      fields: "id",
    })
    .catch(console.log);
  return res2;  // or return res2.data;
}

module.exports = {
  // Load client secrets from a local file.
  read: async function (filePath) {
    return await readFile(filePath);
  }, // <--- Modified
};
  • 我认为在上面修改后的脚本中,您的server.js无需修改即可使用。

注意:

  • 在您的脚本中,使用了 const { client_secret, client_id, redirect_uris } =credentials.web。如果没有出现错误,请使用这个。如果出现错误,请尝试使用 const { client_secret, client_id, redirect_uris } =credentials.installed

引用:

关于javascript - 从node.js googledrive api返回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62993880/

相关文章:

JavaScript:不可枚举的属性 - 何时何地?

javascript - 更新angularjs中的现有元素ng-repeat列表?

node.js - kubernetes中redis和nodejs出错

node.js - 在 Node.js 中事务性地写入文件

oauth-2.0 - 在没有第 3 方的情况下对 API 使用 oauth

java - 我们如何使用 Amazon cognito 作为其他应用程序(例如 google 或 facebook)的身份提供商

ios - 使用 Swift p2/OAuth2 并行刷新 OAuth2 访问 token 请求

javascript - 如何在开始播放视频时向videojs添加事件监听器?

javascript - Date.toLocaleDateString() 不适用于 Nodejs v10.14.2

c++ - NodeJS 和 C++ 之间的通信