39

需要有关通过 api 将文件插入谷歌驱动器的帮助。用于此目的的 api 文档并没有明确说明如何通过 http post 请求发送文件的实际正文。

4

5 回答 5

65

插入操作的文档已经包含了许多编程语言的示例,这里是如何使用基于 HTTP 的 Google Drive API 协议来完成的。

首先,将新文件元数据发布到 Drive 端点。它必须采用文件资源 JSON 对象的形式:

POST /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
...

{
  "title": "file_name.extension",
  "mimeType": "mime/type",
  "description": "Stuff about the file"
}

响应正文将是新创建的文件资源的 JSON 表示。它看起来像:

{
  "kind": "drive#file",
  "id": string,
  "etag": etag,
  "selfLink": string,
  "title": "file_name",
  "mimeType": "mime/type",
  "description": "Stuff about the file"
  ...
  "downloadUrl": string,
  ...
}

这是对已创建文件条目的确认。现在您需要上传内容。为此,您需要获取上述响应中id JSON 属性给出的文件 ID,并使用 OAuth 2.0 授权请求将实际文件的内容发送到上传端点。它应该看起来像:

PUT /upload/drive/v2/files/{id}?uploadType=media HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
Content-Type: mime/type

<file content here>

你完成了:)

还有一种方法可以在 1 个使用多部分请求的单个 POST 请求中执行此操作,您可以在该请求中将文件的元数据与内容同时发布。这是一个例子:

POST /upload/drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer <OAuth 2.0 access token here>
Content-Type: multipart/form-data; boundary=287032381131322
...

--287032381131322
Content-Type: application/json

{
  "title": "file_name.extension",
  "mimeType": "mime/type",
  "description": "Stuff about the file"
}
--287032381131322
Content-Type: mime/type

<file content here>
--287032381131322--

响应将包含新创建文件的元数据。您还可以在请求的子部分中使用Content-Transfer-Encoding: base64标头,以便能够将文件的数据作为 Base 64 编码传递。

最后还有一个可恢复的上传协议,方便上传大文件,提供暂停/恢复功能和/或上传具有不稳定互联网连接的文件。

PS:其中大部分内容现在在Drive 的文件上传文档中进行了描述。

于 2012-04-25T20:54:10.767 回答
17

感谢您的解释!这让我花了好几个小时在蹩脚的谷歌 SDK 文档上兜圈子(对不起,我不得不吐槽)。

这是我制作的一个函数,它将更新一个文本文件(如您所见,我正在更新 html):

  function gd_updateFile(fileId, folderId, text, callback) {

    const boundary = '-------314159265358979323846';
    const delimiter = "\r\n--" + boundary + "\r\n";
    const close_delim = "\r\n--" + boundary + "--";

    var contentType = "text/html";
    var metadata = {'mimeType': contentType,};

    var multipartRequestBody =
        delimiter +  'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter + 'Content-Type: ' + contentType + '\r\n' + '\r\n' +
        text +
        close_delim;

    if (!callback) { callback = function(file) { console.log("Update Complete ",file) }; }

    gapi.client.request({
        'path': '/upload/drive/v2/files/'+folderId+"?fileId="+fileId+"&uploadType=multipart",
        'method': 'PUT',
        'params': {'fileId': fileId, 'uploadType': 'multipart'},
        'headers': {'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'},
        'body': multipartRequestBody,
        callback:callback,
    });
  }

这是 google 示例的混搭(它使用来自上传的二进制文件),以及上面@Nivco 的精彩解释。

于 2012-12-21T07:21:11.400 回答
8

4年后,这仍然很难弄清楚。我接受了@user1158023 的回答来支持上传图片。我正在使用 API v3 和 superagent.js 来帮助我(因为 gapi.client.request 正在将请求发送到 content.googleapis.com!?)。希望有人会发现这很有用。

function gd_uploadFile(name, contentType, data, callback) {
    const boundary = '-------314159265358979323846';
    const delimiter = "\r\n--" + boundary + "\r\n";
    const close_delim = "\r\n--" + boundary + "--";

    contentType = contentType || "text/html";
    var metadata = {
        name: name,
        'mimeType': contentType
    };

    var multipartRequestBody =
        delimiter +  'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter +
        'Content-Type: ' + contentType + '\r\n';

    //Transfer images as base64 string.
    if (contentType.indexOf('image/') === 0) {
        var pos = data.indexOf('base64,');
        multipartRequestBody += 'Content-Transfer-Encoding: base64\r\n' + '\r\n' +
            data.slice(pos < 0 ? 0 : (pos + 'base64,'.length));
    } else {
        multipartRequestBody +=  + '\r\n' + data;
    }
    multipartRequestBody += close_delim;

    if (!callback) { callback = function(file) { console.log("Update Complete ", file) }; }

    superagent.post('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart').
        set('Content-Type', 'multipart/form-data;  boundary="' + boundary + '"').
        set('Authorization', 'Bearer ' + gapi.auth.getToken().access_token).
        send(multipartRequestBody).
        end(function () {
            console.log(arguments);
        });
}

//On upload
$('#file')[0].onchange = function () {
    var file = $('#file')[0].files[0];
    if (file && file.type === 'image/jpeg') {
        var reader = new FileReader();
        reader.onloadend = function () {
            var data = reader.result;
            gd_uploadFile('img.jpg', 'image/jpeg', data, function () {
                console.log(arguments);
            });
        }
        reader.readAsDataURL(file);
    }
};

索引.html

...
<form>
    <span>Upload: </span><input id="file" type="file" name="myFile">
</form>
...
于 2016-01-11T21:42:31.073 回答
3

我希望有更好的驱动器 gapis v3 示例...我花了一些时间才弄清楚如何将新内容上传到使用创建的现有文件中

gapi.client.drive.files.create({ "name" : "savefile.txt" }).execute(function(file) { console.log("Created file " + file.name + " id: " + file.id); });

但最终我尝试了将fileId添加到路径并将方法更改为PATCH的“幸运”组合

function uploadFile(id, text)                                                                                                                                                          
{
  var auth_token = gapi.auth.getToken().access_token;

  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  var metadata = { 
      description : 'savefile for my game',
      'mimeType': 'application/json'
  };  

  var multipartRequestBody =
    delimiter +  'Content-Type: application/json\r\n\r\n' +
    JSON.stringify(metadata) +
    delimiter + 'Content-Type: application/json\r\n\r\n' +
    text +
    close_delim;

  gapi.client.request
    ( { 
     'path': '/upload/drive/v3/files/'+id,
     'method': 'PATCH',
     'params': {'fileId': id, 'uploadType': 'multipart'},
     'headers': { 'Content-Type': 'multipart/form-data; boundary="' + boundary + '"', 'Authorization': 'Bearer ' + auth_token, },
     'body': multipartRequestBody 
     }).execute(function(file) { console.log("Wrote to file " + file.name + " id: " + file.id); }); 
}

但我想现在https://developers.google.com/drive/v3/reference/files/update上的整个文档对我来说开始有意义了:-)

于 2016-05-02T20:09:56.923 回答
2

Google Drive API团队于2015 年底发布了 v3,并在该版本中insert()更改了名称create()以更好地反映文件操作。文档也得到了改进:现在有一个专门用于上传(简单、多部分和可恢复)的特殊指南,附带 Java、Python、PHP、C#/.NET、Ruby、JavaScript/Node.js 和 iOS 中的示例代码/Obj-C 用于上传常规文件,另一个用于将 CSV 文件作为 Google 表格导入。

只是为了直截了当地显示,下面是另一种Python 解决方案(针对文档中的示例),用于不需要apiclient.http.MediaFileUpload该类的短文件(“简单上传”)。此代码段假定您的身份验证代码适用于您的服务端点所在DRIVE的最小身份验证范围为https://www.googleapis.com/auth/drive.file.

# filenames & MIMEtypes
DST_FILENAME = 'inventory'
SRC_FILENAME = DST_FILENAME + '.csv'
SHT_MIMETYPE = 'application/vnd.google-apps.spreadsheet'
CSV_MIMETYPE = 'text/csv'

# Import CSV file to Google Drive as a Google Sheets file
METADATA = {'name': DST_FILENAME, 'mimeType': SHT_MIMETYPE}
rsp = DRIVE.files().create(body=METADATA, media_body=SRC_FILENAME).execute()
if rsp:
    print('Imported %r to %r (as %s)' % (SRC_FILENAME, DST_FILENAME, rsp['mimeType']))

请注意,如果您正在编写 Android 应用程序,则有一个单独的适用于 Android 的 Google Drive API及其自己的一组文档。最后,如果您在 Google Apps Script 上使用 JavaScript,Drive Service 原生对象Drive Advanced Service仍在使用 API v2。

于 2017-03-15T18:28:00.803 回答