导入和导出项目

由于 Apps 脚本项目位于 Google 云端硬盘中,因此开发者可以使用 Google Drive API(不要与 Apps 脚本中的 Drive 服务混淆)导入和导出 Apps 脚本源代码。

例如,开发者可以在本地计算机上使用自己喜欢的代码编辑器编写新的 Apps 脚本代码,并使用 Git 等版本控制系统与其他开发者协作。当版本最终确定后,她可以使用 REST API 将文件上传(导入)到 Google 云端硬盘,这些文件可以像任何其他 Apps 脚本项目一样使用。

您可以在本地版本上进行代码更改,然后使用 Google Drive API 将这些更改同步到 Apps 脚本项目。您可以将现有项目从 Google 云端硬盘下载(导出)到本地计算机。

功能和限制

如果您想使用 Google Drive API 导入或导出项目,请注意以下事项:

  1. 服务器端脚本文件应以“.gs”结尾。您可能希望使用 .js 文件在本地进行开发,但在导入到 Google 云端硬盘之前,请务必重命名文件,使其包含 .gs 扩展名。
  2. 客户端脚本文件需要以“.html”结尾。这包括客户端的 .html、.js 或 .css 文件。同样,您可以使用其他扩展程序在本地进行开发,但必须先添加 .html 扩展程序,然后才能导入到 Google 云端硬盘。
  3. 将项目文件导入到 Google 云端硬盘时,这些文件中的所有现有数据都会被覆盖。您无法附加或插入部分文本;必须更新整个文件。
  4. 服务器端脚本文件必须包含有效的 JavaScript。如果服务器 .js 文件中存在错误,Google Drive API 更新调用将失败并显示 5xx 错误。您可以在导入之前对代码进行 linting,以防止出现这种情况。
  5. 无法导入空文件。如果您尝试上传空文件,Google 云端硬盘 API 更新调用将失败并显示 5xx 错误。
  6. 只能导入或导出独立脚本。无法通过 Google Drive API 访问容器绑定的脚本。
  7. 只能导入或导出源代码。项目属性或日志等资源也不会通过 Google Drive API 公开。无法通过 Google Drive API 执行脚本版本控制、发布或执行脚本等操作。
  8. 您并非只能使用单个服务器 Code.gs 文件。您可以将服务器代码分布在多个文件中,以便于开发。所有服务器文件都会加载到同一全局命名空间中,因此,如果您想提供安全的封装,请使用 JavaScript 类。

Drive API

Google Drive API 允许开发者以编程方式访问 Google 云端硬盘中的文件。此 API 使用 GET 下载文件,使用 PUT/POST 上传文件。如需详细文档和快速入门指南,请参阅 Google Drive API 概览页面

本指南将重点介绍如何使用以下调用通过 Files 资源列出和移动文件:

授权

向 Google Drive API 发出的所有请求都必须由经过身份验证的用户通过 OAuth 2.0 协议进行授权。如需了解详情,请参阅 Google Drive API 授权文档

除了应用可能需要的其他范围(例如 https://www.googleapis.com/auth/drive)之外,尝试导入或导出 Google Apps 脚本项目的所有应用都必须请求以下特殊范围:

https://www.googleapis.com/auth/drive.scripts

列出现有项目

如需列出云端硬盘中的所有 Apps 脚本项目,请使用 Files 资源查询 MIME 类型为 application/vnd.google-apps.script 的文件。 如需过滤响应,使其仅包含您拥有的文件,请添加搜索参数 'me' in owners

以下是一个示例请求和响应,其中显示了通过 JSON 响应返回的 Apps 脚本项目数组。

GET https://www.googleapis.com/drive/v2/files?q=mimeType%3D'application%2Fvnd.google-apps.script'+and+'me'+in+owners
Authorization:  Bearer ya29.fakebearerstring
{
 "kind": "drive#fileList",
 "etag": "\"kjsas92/f3zGUXczKMxEB_9ZTMRFOF3d1ZU\"",
 "selfLink": "https://www.googleapis.com/drive/v2/files?q=mimeType%3D'application/vnd.google-apps.script'+and+'me'+in+owners",
 "items": [
  {
   "kind": "drive#file",
   "id": "1vi0uwcMdHsRv1YFtgq7XdiTGSdqgjIYpdQNC0A_Udn79LOhH0vYL132D",
   "etag": "\"kjsas92/MTM3MDk3ODY5ODQyNg\"",
   "selfLink": "https://www.googleapis.com/drive/v2/files/1vi0uwcMdHsRv1YFtgq7XdiTGSdqgjIYpdQNC0A_Udn79LOhH0vYL132D",
   "alternateLink": "https://script.google.com/a/google.com/d/1vi0uwcMdHsRv1YFtgq7XdiTGSdqgjIYpdQNC0A_Udn79LOhH0vYL132D/edit?usp=drivesdk",
   "iconLink": "https://ssl.gstatic.com/docs/doclist/images/icon_11_script_list.png",
   "title": "Mail merge",
   "mimeType": "application/vnd.google-apps.script",
   "description": "",
   "labels": {
    "starred": false,
    "hidden": false,
    "trashed": true,
    "restricted": false,
    "viewed": true
   },
   "createdDate": "2013-06-11T19:24:45.188Z",
   "modifiedDate": "2013-06-11T19:24:58.426Z",
   "modifiedByMeDate": "2013-06-11T19:24:58.426Z",
   "lastViewedByMeDate": "2013-06-11T19:24:58.426Z",
   "parents": [
    {
     "kind": "drive#parentReference",
     "id": "0APdyIOzo7bWDUk9PVA",
     "selfLink": "https://www.googleapis.com/drive/v2/files/1vi0uwcMdHsRv1YFtgq7XdiTGSdqgjIYpdQNC0A_Udn79LOhH0vYL132D/parents/0APdyIOzo7bWDUk9PVA",
     "parentLink": "https://www.googleapis.com/drive/v2/files/0APdyIOzo7bWDUk9PVA",
     "isRoot": true
    }
   ],
   "exportLinks": {
    "application/json": "https://script.google.com/feeds/download/export?id=1234567890abcefghijklmnopqrstuvwxyz&format=json"
   },
   "userPermission": {
    "kind": "drive#permission",
    "etag": "\"kjsas92/259X2r5DVstv1CcIQTjt_RQPSW8\"",
    "id": "me",
    "selfLink": "https://www.googleapis.com/drive/v2/files/1vi0uwcMdHsRv1YFtgq7XdiTGSdqgjIYpdQNC0A_Udn79LOhH0vYL132D/permissions/me",
    "role": "owner",
    "type": "user"
   },
   "quotaBytesUsed": "0",
   "ownerNames": [
    "John Doe"
   ],
   "owners": [
    {
     "kind": "drive#user",
     "displayName": "John Doe",
     "picture": {
      "url": "https://lh4.googleusercontent.com/-yd1rIb6Pe2Y/AAAAAAAAAAI/AAAAAAAAAGs/PP5vTuZonik/s64/photo.jpg"
     },
     "isAuthenticatedUser": true,
     "permissionId": "1234566789"
    }
   ],
   "lastModifyingUserName": "John Doe",
   "lastModifyingUser": {
    "kind": "drive#user",
    "displayName": "John Doe",
    "picture": {
     "url": "https://lh4.googleusercontent.com/-yd1rIb6Pe2Y/AAAAAAAAAAI/AAAAAAAAAGs/PP5vTuZonik/s64/photo.jpg"
    },
    "isAuthenticatedUser": true,
    "permissionId": "1234566789"
   },
   "editable": true,
   "writersCanShare": true,
   "shared": false,
   "explicitlyTrashed": true,
   "appDataContents": false
  }
 ]
}

如果您知道某个 Apps 脚本项目的文件 ID,可以使用以下 API 调用直接获取该项目:

GET https://www.googleapis.com/drive/v2/files/1234567890abcefghijklmnopqrstuvwxyz
Authorization:  Bearer ya29.fakebearerstring

从云端硬盘导出项目

从 API 获取 File 资源后,exportLinks 属性将包含一个网址,用于获取项目内容(以 JSON 数据形式)。此网址的示例可能如下所示:

https://script.google.com/feeds/download/export?id=1234567890abcefghijklmnopqrstuvwxyz&format=json

向此网址发出请求,以检索项目本身的内容。 确保您包含具有相同 OAuth Bearer 令牌的 Authorization 标头

以下是请求和响应示例:

GET https://script.google.com/feeds/download/export?id=1234567890abcefghijklmnopqrstuvwxyz&format=json
Authorization:  Bearer ya29.fakebearerstring
{
  "files": [
    {
      "id":"9basdfbd-749a-4as9b-b9d1-d64basdf803",
      "name":"Code",
      "type":"server_js",
      "source":"function doGet() {\n  return HtmlService.createHtmlOutputFromFile(\u0027index\u0027);\n}\n"
    },
    {
      "id":"3asf7c0d-1afb-4a9-8431-5asdfc79e7ae",
      "name":"index",
      "type":"html",
      "source":"\u003chtml\u003e\n  \u003cbody\u003e\n    Hello, world!\n  \u003c/body\u003e\n\u003c/html\u003e"
    }
  ]
}

上述示例包含 HTML 服务指南中的简单 Web 应用的代码。请注意,您会获得一个 Files 数组,每个元素都具有以下 4 个属性:

id 项目内文件的内部标识符,在更新期间引用此文件时需要用到。
name 不含扩展名的文件名,如脚本编辑器中所示。
type 这两种文件分别是 server_js 和 html。
source 文件中包含的编码源代码。

将项目导入到云端硬盘

如需更新现有项目,请使用适当的 fileId 对文件 update API 进行 HTTP PUT 调用。 以下示例展示了媒体上传部分的交易示例。借助其中一个客户端库,您的应用可以轻松地在同一次上传调用中包含元数据和媒体。请注意,Content-Type 标头指定了此示例中上传的内容的类型。

PUT https://www.googleapis.com/upload/drive/v2/files/1234567890abcefghijklmnopqrstuvwxyz
Authorization:  Bearer ya29.fakebearerestring
Content-Type:  application/vnd.google-apps.script+json
{
  "files": [
    {
      "id":"9basdfbd-749a-4as9b-b9d1-d64basdf803",
      "name":"Code",
      "type":"server_js",
      "source":"function doGet() {\n  return HtmlService.createHtmlOutputFromFile(\u0027index\u0027);\n}\n"
    },
    {
      "id":"3asf7c0d-1afb-4a9-8431-5asdfc79e7ae",
      "name":"index",
      "type":"html",
      "source":"\u003chtml\u003e\n  \u003cbody\u003e\n    New message!!\n  \u003c/body\u003e\n\u003c/html\u003e"
    }
  ]
}

在项目中创建新文件

如需在项目中创建新文件,请发送不含 id 属性的文件 PUT 请求。如果您包含具有未知标识符的文件,系统会抛出错误消息。

删除项目中的文件

如需从项目中删除某个文件,请发送不包含该文件(但包含项目中的所有其他文件)的 PUT 请求。在导入过程中未发送回服务器的任何文件都将从服务器中删除。

重命名项目中的文件

如需重命名项目中的文件,请发送 PUT 请求,其中包含现有的 id,但使用新的 name。请注意,服务器会忽略任何将 type 更改为其他值的尝试。

新建项目

如需创建新项目,请向文件 insert API 发送 POST 请求。与 update 调用类似,您可以使用客户端库来添加项目名称和说明等元数据。

以下是媒体上传交易的示例。这将在您的云端硬盘中创建一个名为“无标题”的项目。网址中的 convert 参数是必需的。 与 update 调用一样,Content-Type 标头是必需的。

POST https://www.googleapis.com/upload/drive/v2/files?convert=true
Authorization:  Bearer ya29.fakebearerestring
Content-Type:  application/vnd.google-apps.script+json
{
  "files": [
    {
      "name":"Code",
      "type":"server_js",
      "source":"function doGet() {\n  return HtmlService.createHtmlOutputFromFile(\u0027index\u0027);\n}\n"
    },
    {
      "name":"index",
      "type":"html",
      "source":"\u003chtml\u003e\n  \u003cbody\u003e\n    Hello, world!!\n  \u003c/body\u003e\n\u003c/html\u003e"
    }
  ]
}