使用 google drive appDataFolder 在客户端使用 javascript 存储应用状态

Using google drive appDataFolder to store app state with javascript on the client side

提问人:Adrian Bota 提问时间:7/6/2016 最后编辑:Adrian Bota 更新时间:7/25/2016 访问量:1915

问:

我一直在尝试创建这个非常简单的 Web 应用程序,它使用 google drive appDataFolderjson 格式存储和读取其状态。但是,v3 驱动器 API 的文档不包含有关如何轻松实现此目的的综合示例。

到目前为止,我能够授权加载 google drive api,但如果配置 json 文件不存在,我无法创建它,或者更新其内容或读取(如果存在)。

我所做的调用是:gapi.client.drive.files.get 检索配置 json,gapi.client.drive.files.create 创建配置 json 和 gapi.client.drive.files.update 更新其内容。

我一直在尝试使用 javascript Blob 对象来表示我的文件及其内容,但没有任何效果。

鉴于我有例如 { test: true } stringified 的配置并且文件名my-app.json,我将如何调用 gapi.client.drive.files API 来创建/更新/读取此配置?

尝试通过首先获取应用程序文件夹中的文件列表,按名称匹配配置文件,获取其 id,然后使用 id 再次请求该文件来执行检索部分。但是由于我无法创建文件,我不确定它是否有效。

代码当前如下所示(请务必注意,此代码在客户端浏览器中运行,而不是在服务器上运行):

var config = require('../config/google-drive-config');

var authorize = function (immediate) {
  return gapi.auth.authorize({
    'client_id': config.clientId,
    scope: config.scopes.join(' '),
    immediate: !!immediate
  });
};

var loadDriveAPI = function () {
  return gapi.client.load(
    config.apiName,
    config.apiVersion
  );
};

var loadAppDataFileId = function () {
  return gapi.client.drive.files
    .list({
      spaces: 'appDataFolder'
    })
    .then(function(response) {
      return _(response.files)
        .find({ name: config.appDataFile })
        .get('id')
        .value();
    });
};

var loadAppData = function (fileId) {
  return gapi.client.drive.files
    .get({
      'fileId': fileId
    });
};

var saveAppData = function (appData, fileId) {
  var resource = {
    'name': config.appDataFile,
    'parents': 'appDataFolder'
  };

  var media = {
    mimeType: 'application/json',
    body: new Blob([JSON.stringify(appData)], { type: 'application/json' })
  };

  if (fileId) {
    return gapi.client.drive.files
      .update({
        fileId: fileId,
        media: media
      });
  }

  return gapi.client.drive.files
    .create({
      resource: resource,
      media: media,
      fields: 'id'
    });
};

module.exports = {
  authorize: authorize,
  loadDriveAPI: loadDriveAPI,
  loadAppDataFileId: loadAppDataFileId,
  loadAppData: loadAppData,
  saveAppData: saveAppData
};

javascript json google-drive-api 客户端

评论

0赞 Marc Went 7/6/2016
我现在有完全相同的问题。我想更新我的文件,我有 fileId。并有一些我想存储的 json 数据。
0赞 Zig Mandel 7/6/2016
欢迎来到 stackoverflow。了解如何编写一个好的 stackoverflow 问题 为了改进你的问题,向我们展示创建不起作用的代码。
0赞 Adrian Bota 7/6/2016
是的,我现在意识到这个问题没有正确表述。我将使用我的代码进行更新。感谢您的反馈@ZigMandel
0赞 Marc Went 7/6/2016
@AdrianBota您的负载缺少某些内容: var loadAppData = function (fileId, callback) { return gapi.client.drive.files .get({ 'fileId': fileId, alt: “media” }).execute(callback);这样,您可以加载文件的内容。我需要找到如何运行gapi.client.drive.files.update函数 - 您需要它来保存文件,而不是创建(至少,我认为至少应该这样做)
0赞 Marc Went 7/6/2016
@AdrianBota我在之前的评论中犯了一个错误,但你确实调用了更新。

答:

12赞 Adrian Bota 7/19/2016 #1

经过反复试验,我终于让它工作了。我无法让gapi.client.drive.files.update工作,但它适用于gapi.client.request:

var auth = function (immediate) {
  return gapi.auth.authorize({
    'client_id': 'YOUR CLIENT ID GOES HERE',
    // Permissions here can be more restrictive
    scope: 'https://www.googleapis.com/auth/drive',
    immediate: immediate
  });
};

var silentAuth = function () {
  return auth(true);
};

var popupAuth = function () {
  return auth(false);
};

var loadDriveAPI = function () {
  return global.gapi.client.load('drive', 'v3');
};

var getAppDataFile = function () {
  return gapi.client.drive.files
    .list({
      q: 'name="your-app-data-file-name.json"',
      spaces: 'appDataFolder',
      fields: 'files(id)'
    }).then(
      function (data) {
        if (_.isEmpty(data.result.files)) {
          throw "no files found";
        }

        return {
          fileId: data.result.files[0].id
        }
      }
    );
};

var createAppDataFile = function () {
  return gapi.client.drive.files
    .create({
      resource: {
        name: 'your-app-data-file-name.json',
        parents: ['appDataFolder']
      },
      fields: 'id'
    }).then(function (data) {
      return {
        fileId: data.result.id
      };
    });
};

var getAppDataFileContent = function (fileId) {
  return gapi.client.drive.files
    .get({
      fileId: fileId,
      // Download a file — files.get with alt=media file resource
      alt: 'media'
    }).then(function (data) {
      return {
        fileId: fileId,
        appData: data.result
      };
    });
};

var saveAppData = function (fileId, appData) {
  return gapi.client.request({
    path: '/upload/drive/v3/files/' + fileId,
    method: 'PATCH',
    params: {
      uploadType: 'media'
    },
    body: JSON.stringify(appData)
  });
};

module.exports = {
  silentAuth: silentAuth,
  popupAuth: popupAuth,
  loadDriveAPI: loadDriveAPI,
  getAppDataFile: getAppDataFile,
  createAppDataFile: createAppDataFile,
  getAppDataFileContent: getAppDataFileContent,
  saveAppData: saveAppData
};

上述所有方法都返回一个 promise。对 lodash 有依赖性

评论

0赞 bochko 3/30/2017
我无法表达我对这个答案的感激之情。完美无缺,并且解决了许多 Google API 文档似乎保持沉默的问题。谢谢!
0赞 Daniel 10/30/2020
它应该是谷歌页面上的官方教程。我在阅读凌乱的谷歌文档 3 小时后找到了它,几乎辞去了实施谷歌驱动器支持......但这效果很好。
0赞 Michael Camden 10/7/2023
谢谢你的这个片段,只是为我节省了大量的调试时间
3赞 Adrian Bota 7/25/2016 #2

我创建了一个库来处理所有样板,并公开了一个非常简单、直接的 API:https://github.com/adrianbota/gdrive-appdata

评论

1赞 phlummox 10/5/2020
解释一下样板是什么可能会有所帮助。