Google Drive可使用javascript恢复上传

时间:2013-07-29 08:11:53

标签: javascript google-drive-api

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

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

如果我使用“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没有答案。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

什么有效

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

这是一个丑陋的Promise和回调代码混合,对我有用。作为先决条件,gapiUploaderForGoogleDriveJSZip需要通过<script>标记加载。该片段还省略了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月,由于issue where gapi removes the PUT payload

,使用gapi.client.request电话上传二进制blob无法正常工作

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