Search code examples
javascriptapizipdrivejszip

Google Drive API - Get file and zip with JSZip is returning corrupt file


I'm using Google Drive's API to get the BLOB of a file and attempting to give that BLOB data to JSZip to zip, but I'm having issues.

The specific snippet looks like this:

var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://www.googleapis.com/drive/v3/files/"+file_id+"?alt=media",
    "method": "GET",
    "headers": {
        "responseType": "blob",
        "Authorization": "Bearer "+bearer_token
     }
}

$.ajax(settings).done(function (response, status, xhr) {
    console.log(response);
    zip.file(filename, response);

    zip.generateAsync({type:"blob"}, function updateCallback(metadata) {
        var msg = "progression : " + metadata.percent.toFixed(2) + " %";
        if(metadata.currentFile) {
            msg += ", current file = " + metadata.currentFile;
        }
        showMessage(msg);
        updatePercent(metadata.percent|0);
     })
     .then(function callback(blob) {
         saveAs(blob, "example.zip");
         showMessage("done !");
     }, function (e) {
         showError(e);
     });
 });

I used Postman to do the API testing which was returning expected results. I've tried zipping several image/pdf/zip files all of which have come back corrupted. The only thing that has worked so far has been a PHP file. Google Drive API is returning the BLOB data properly and everything looks right in JSZip generated zip file (file name, file size, etc.) but upon opening the file from the zip I get errors that indicate the file is corrupt.

Any ideas?

Thanks for your help, in advance!


Solution

    • You want to retrieve a zip file from Google Drive.
    • You want to achieve this using Javascript.
    • You have already been able to get and put the file using Drive API.

    If my understanding is correct, how about this modification?

    Modification point:

    • I think that the reason of your issue is that the zip file is retrieved as the string data.
      • For this situation, I used fetch.

    Modified script:

    Please modify as follows.

    From:
    var settings = {
        "async": true,
        "crossDomain": true,
        "url": "https://www.googleapis.com/drive/v3/files/"+file_id+"?alt=media",
        "method": "GET",
        "headers": {
            "responseType": "blob",
            "Authorization": "Bearer "+bearer_token
         }
    }
    
    $.ajax(settings).done(function (response, status, xhr) {
    
    To:
    const url = "https://www.googleapis.com/drive/v3/files/" + file_id + "?alt=media";
    fetch(url, {
      method: "GET",
      dataType: "binary",
      responseType: "blob",
      headers: {Authorization: "Bearer " + bearer_token},
      // crossDomain: true, // This might not be required.
    })
    .then(res => res.blob())
    .then(response => {
    
    • In above modified script, response is a blob.
    • Please set file_id and bearer_token

    For testing:

    As a test sample script, how about the following script? When you run this script, the downloaded zip file is saved to the local PC as the filename of sample.zip. I thought that the script might be able to be tested using this script.

    const url = "https://www.googleapis.com/drive/v3/files/" + file_id + "?alt=media";
    fetch(url, {
      method: "GET",
      dataType: "binary",
      responseType: "blob",
      headers: {Authorization: "Bearer "+bearer_token},
    })
    .then(res => res.blob())
    .then(blob => {
      var a = document.createElement("a");
      a.href = URL.createObjectURL(blob);
      a.target = "_blank";
      a.download = "sample.zip";
      a.click();
    });
    

    Note:

    • This is a simple sample script. So please modify this for your situation.

    References:

    If I misunderstood your question and this was not the direction you want, I apologize.