2

Google APIs Client Library for JavaScriptresumable upload typeを使用して、ファイルを Google ドライブにアップロードしようとしています。

認証してアップロード URI を正常に取得しましたが、実際のデータの送信中に問題が発生しました。ファイルに ASCII 文字のみが含まれている場合、ファイルはドライブに正常に送信されますが、特殊文字 (åäö) またはバイナリ ファイル (PNG など) の場合、ファイルは破損します。私の推測では、プロセスのどこかでファイルがクライアント側でユニコードにエンコードされていると思います。

「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には同様の質問があり、回答はありません。

4

2 に答える 2

1

Blob 型はXMLHttpRequest実装のホット トピックであり、真に成熟したものではありません。base64エンコーディングに固執することをお勧めします。クライアント側のブラウザ アプリが非常に大きなファイルを Google ドライブに直接アップロードすることはほとんどないため、Google の JavaScript クライアント ライブラリは再開可能なアップロードをサポートしていません。

于 2013-07-29T12:59:41.203 に答える
0

機能するもの

バイナリ blob をアップロードするには、github/googleapi の cors -upload-sampleを使用するか、Gapi クライアントから取得する Gistフォーク UploaderForGoogleDriveを使用します。access_token

これは、私にとってはうまくいくPromiseとコールバックコードの醜い混合物です。前提条件として、gapiUploaderForGoogleDriveはタグJSZip経由でロードする必要があります。<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 月の時点で、gapi が PUT ペイロードを削除する問題gapi.client.requestのため、呼び出しでバイナリ BLOB をアップロードすることはできません。

また、動作する base64 を使用してみましたgapi。ただし、真のバイナリではなく、base64 ファイルをデポジットします。少なくとも私にとっては、半分は機能していましたが、CORS 関連のエラーと応答の隠蔽が発生しました。

于 2017-11-04T04:29:54.977 に答える