Search code examples
javascriptgoogle-apps-scriptzip

Check zip file contents in Google Drive using Apps Script not unzipping it?


Do you know how to read ZIP file contents (e.g. list files in zip, compression ratio of files ...) in Google Drive by using Apps Script? Thanks.


Solution

  • I can't find Apps Script API for my purpose. I wrote simple codes to read file name and its compress ratio in zip file. (It works with file size < 50MB because of Blob.getBytes() limitation).

    Referred this document for ZIP file format.

    const ZIP_FILE_ID = "... Add your file ID here ...";
    const OFFSET_TO_COMPRESS_SIZE = 18;
    const OFFSET_TO_UNCOMPRESS_SIZE = 22;
    const OFFSET_TO_FILENAME_LEN = 26;
    const OFFSET_TO_EXTRA_LEN = 28;
    const OFFSET_TO_FILENAME = 30;
    
    function checkEntrySignature(bytesData, start) {
      if (bytesData[start] != 0x50) return false;
      if (bytesData[start + 1] != 0x4B) return false;
      if (bytesData[start + 2] != 0x03) return false;
      if (bytesData[start + 3] != 0x04) return false;
      return true;
    }
    
    function read4bytesAsNumber(bytesData, start) {
      let numArray = Uint8Array.from(bytesData.slice(
        start, start + 4));
      var number = numArray[0];
      number += numArray[1] << 8;
      number += numArray[2] << 16;
      number += numArray[3] << 24;
      return number;
    }
    
    function read2bytesAsNumber(bytesData, start) {
      let numArray = Uint8Array.from(bytesData.slice(
        start, start + 2));
      var number = numArray[0];
      number += numArray[1] << 8;
      return number;
    }
    
    function readBytesAsString(bytesData, start, length) {
      let slicedBytes = bytesData.slice(start, start + length);
      return String.fromCharCode.apply(null, slicedBytes);
    }
    
    function myFunction() {
      let zipFile = DriveApp.getFileById(ZIP_FILE_ID);
      let zipBytes = zipFile.getBlob().getBytes();
      var entryIndex = 0;
    
      while(true) {
        isZipEntry = checkEntrySignature(zipBytes, entryIndex)
        if (isZipEntry == false) {
          break;
        }
        compressedSize = read4bytesAsNumber(zipBytes,
          entryIndex + OFFSET_TO_COMPRESS_SIZE);
        uncompressedSize = read4bytesAsNumber(zipBytes,
          entryIndex + OFFSET_TO_UNCOMPRESS_SIZE);
        compressRatio = 1 - compressedSize / uncompressedSize;
        fileNameLength = read2bytesAsNumber(zipBytes,
          entryIndex + OFFSET_TO_FILENAME_LEN);
        extraFieldLength = read2bytesAsNumber(zipBytes,
          entryIndex + OFFSET_TO_EXTRA_LEN);
        fileName = readBytesAsString(zipBytes,
          entryIndex + OFFSET_TO_FILENAME, fileNameLength);
    
        Logger.log(fileName + ", compressed:" + compressRatio);
        
        // calculate index to next entry
        entryIndex = entryIndex + OFFSET_TO_FILENAME + 
          compressedSize + fileNameLength + extraFieldLength;
      }
    }