【问题标题】:Google Drive resumable upload with javascript使用 javascript 进行 Google Drive 可恢复上传
【发布时间】:2013-07-28 22:41:22
【问题描述】:

我正在尝试使用 Google APIs Client Library for JavaScriptresumable upload type 将文件上传到 Google 云端硬盘。

我成功验证并获取了上传 URI,但在发送实际数据时遇到了问题。如果文件仅包含 ASCII 字符,则文件会成功发送到云端硬盘,但如果是特殊字符 (åäö) 或二进制文件(例如 PNG),则文件会损坏。我的猜测是,在进程的某个地方,文件在客户端被编码为 un​​icode。

如果我使用“btoa()”将原始数据编码为 base64 并将标头“Content-Encoding: base64”添加到数据发送请求中,则文件上传正常。然而,使用这种方法会增加 33% 的开销,这在计划上传的文件大小为 100MB 到 1GB 时是相当大的。

以下是一些代码示例:

获取可续传的上传 URI:

// Authentication is already done
var request = gapi.client.request({
    "path": DRIVE_API_PATH, // "/upload/drive/v2/files"
    "method": "POST",
    "params": {
        "uploadType": "resumable"
    },
    "headers": {
        "X-Upload-Content-Type": self.file.type,
        //"X-Upload-Content-Length": self.file.size
        // If this is uncommented, the upload fails because the file size is
        // different (corrupted file). Manually setting to the corrupted file
        // size doesn't give 400 Bad Request.
    },
    "body": {
        // self.file is the file object from <input type="file">
        "title": self.file.name, 
        "mimeType": self.file.type,
        "Content-Lenght": self.file.size,
    }
});

一次性发送整个文件:

// I read the file using FileReader and readAsBinaryString
// body is the reader.result (or btoa(reader.result))
// and this code is ran after the file has been read
var request = gapi.client.request({
    "path": self.resumableUrl, // URI got from previous request
    "method": "PUT",
    "headers": {
        //"Content-Encoding": "base64", // Uploading with base64 works
        "Content-Type": self.file.type
    },
    "body": body
});

我错过了什么吗?是否可以以二进制流上传文件?我是使用 HTML 和 Javascript 上传文件的新手,我还没有找到任何使用可恢复上传的 Google Javascript 库的示例。 SO中有similar question没有答案。

【问题讨论】:

标签: javascript google-drive-api


【解决方案1】:

Blob 类型是 XMLHttpRequest 实现的热门话题,但它们并不真正成熟。我建议您坚持使用 base64 编码。 Google 的 JavaScript 客户端库不支持可恢复上传,因为客户端浏览器应用不太可能将非常大的文件直接上传到 Google 云端硬盘。

【讨论】:

  • 有趣。这仍然是真的吗? MDN added blob support to XMLHttpRequest 2017 年 7 月。我有一个在浏览器中生成模拟数据的应用程序,并且希望浏览器直接上传一个 zip 文件以驱动最终用户。在从浏览器获得text/csv 可恢复上传后,我发现了这篇文章。
  • 我已经成功地将一个 62MB text/csv 1M 行的文件从浏览器中的循环和公式生成,并使用 Jani 提到的两部分技术进入 Drive。尚未尝试 zip 文件,但很快就会尝试。
  • 我们正在制作一个视频网站,我们希望将我们的数据保存到谷歌驱动器。如果我们不直接上传到谷歌驱动器,我们将不得不先上传到我们的服务器,这对我们来说是一件非常可怕的事情。所以,应该有什么办法可以直接上传大文件。
【解决方案2】:

什么有效

要上传二进制 blob,请使用 github/googleapi 的 cors-upload-sample 或使用 my gist fork, UploaderForGoogleDrive,这将为您从 gapi 客户端中获取 access_token

这是对我有用的 Promise 和回调代码的丑陋混合。作为先决条件,gapi,UploaderForGoogleDrive,JSZip 需要通过&lt;script&gt; 标签加载。 sn-p 也省略了 gapi 初始化和 API 机密,这也是必要的。

function bigCSV(){  // makes a string for a 300k row CSV file
    const rows = new Array(300*1000).fill('').map((v,j)=>{
      return [j,2*j,j*j,Math.random(),Math.random()].join(',');
    });
    return rows.join("\n");
}

function bigZip(){  // makes a ZIP file blob, about 8MB
    const zip = new window.JSZip();
    zip.folder("A").file("big.csv", bigCSV());
    return zip.generateAsync({type:"blob", compression:"DEFLATE"});
    // returns Promise<blob>
}

function upload2(zipcontent){
   'use strict';
    const parent = 'root';
    const spaces = 'drive';
    const metadata = {
      name: 'testUpload2H.zip',
      mimeType: 'application/zip',
      parents: [parent]
    };
    const uploader = new window.UploaderForGoogleDrive({
      file: zipcontent,
      metadata: metadata,
      params: {
        spaces,
        fields: 'id,name,mimeType,md5Checksum,size'
      },
      onProgress: function(x){
         console.log("upload progress:",Math.floor(100*x.loaded/x.total));
      },
      onComplete: function(x){
        if (typeof(x)==='string') x = JSON.parse(x);
        // do something with the file metadata in x
        console.log("upload complete: ");
      },
      onError: function(e){ console.log("upload error: ",e); }
    });
    uploader.upload();
}

function uploadZipFile(){
    'use strict';
    (bigZip()
      .then(upload2)
    );
}

什么不起作用

截至 2017 年 11 月,使用 gapi.client.request 调用上传二进制 blob 将无法正常工作,因为 issue where gapi removes the PUT payload

我也尝试过将 base64 与 gapi 一起使用,效果很好。但存放 base64 文件,而不是真正的二进制文件;以及 cors 模式下的 fetch API,它工作了一半,但产生了与 CORS 相关的错误和响应隐藏,至少对我来说是这样。

【讨论】:

    猜你喜欢
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多