Sidebar

Can I create multiple zip files from a directory that are limited by size?

0 votes
645 views
asked Jan 6, 2020 by brandon-w-8204 (33,270 points)

1 Answer

0 votes

Use the following function and pass it the folder to zip as well as the zip file information:

function assembleZipFileStreamLimitZipSize(directoryToZip,zipFilePath,zipFileName) {
   assembleZipFileStreamConsideringMaxZipFileSize(directoryToZip, '', zipFilePath, zipFileName, null);
}

/**
* Gets a new zip file.
 * 
 * * * * zipFilePath String The path where the zip file(s) will be created and written
 * * * * zipFileName String The "base" name of the zip file.
 * * * * zipFileIndex Integer The unique index number to be appended to this zip file's name. This will create a unique zip file name like zipFile_1.zip
 * * * */
function getZipOutputStream(zipFilePath, zipFileName, zipFileIndex) {
   var zipFileStream;
   var fileSeparator;
   var zipFileCompleteName;
   
   fileSeparator = java.io.File.separator;
   zipFileCompleteName = zipFilePath + fileSeparator + zipFileName + "_" + zipFileIndex + ".zip";
   zipFileStream = new java.util.zip.ZipOutputStream(new java.io.FileOutputStream(zipFileCompleteName));
   zipFileStream.setLevel(java.util.zip.Deflater.BEST_COMPRESSION);
   
   return zipFileStream;
}

/**
* Zips up a directory a zip file. If a zip file's overall compressed size exceeds the desired limit, then subsequent zip files will be created.
 * 
 * * * * baseDirectory String the base directory we are zipping up
 * * * * workingDirectory String the working directory. Used for subfolder traversal and zipping
 * * * * zipFilePath the path where the zip file(s) will be created and written
 * * * * zipFileName the "base" name of the zip file
 * * * * zipFileStream the zip file being written to. The first call to this method SHOULD pass in a null. Subsequent recursive calls will pass in the zip file that was created inside this method. Hacky... but should work
 * * * */
function assembleZipFileStreamConsideringMaxZipFileSize(baseDirectory, workingDirectory, zipFilePath, zipFileName, zipFileStream) {
   var MAX_ZIP_FILE_SIZE = 1000 * 1024 * 10; //5Gb limit
   var currentZipFileIndexAppendedToZipFileName = 1; //each zip file will have a unique number appended to its name, i.e. zipFile_1.zip, zipFile_2.zip, etc.
   var currentZipFileSize = 0; //to compare to our MAX_ZIP_FILE_SIZE
   var directory = new java.io.File(baseDirectory + java.io.File.separator + workingDirectory);
   var bytes = new Packages.java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1024);
   var files = directory.listFiles();
   
   try {
      if (zipFileStream === null) {
         //first time call only, we new up our first zipFileStream. subsequent recursive calls will pass this same zipFileStream in
         zipFileStream = getZipOutputStream(zipFilePath, zipFileName, currentZipFileIndexAppendedToZipFileName);
      }
      
      for (var currentFile = 0; currentFile < files.length; currentFile++) {
         var file = files[currentFile];
         
         if (file.isDirectory()) {
            // if directory, add directory to zip and call add directory files
            assembleZipFileStreamConsideringMaxZipFileSize(baseDirectory, workingDirectory + java.io.File.separator + file.getName(), zipFilePath, zipFileName, zipFileStream);
         } else {
            //NOTE: this is a "lazy" size check... we're not checking if the next file's size + currentZipFileSize > MAX_ZIP_FILE_SIZE... so we'll be exceeding MAX_ZIP_FILE_SIZE by one file
            if (currentZipFileSize > MAX_ZIP_FILE_SIZE) {
               zipFileStream.close();
               currentZipFileIndexAppendedToZipFileName++;
               zipFileStream = getZipOutputStream(zipFilePath, zipFileName, currentZipFileIndexAppendedToZipFileName);
               currentZipFileSize = 0; //reset for next zip file
            }
            // if file, then add to zip
            var inputStream = new java.io.FileInputStream(file);
            var fileName = file.getName();
            var fullPath = StringUtils.replace(workingDirectory + '\\' + fileName, '\\', java.io.File.separator);
            var zipEntry;
            var length;
            
            if (StringUtils.startsWithIgnoreCase(fullPath, java.io.File.separator)) {
               fullPath = StringUtils.substringAfter(fullPath, java.io.File.separator);
            }
            
            qie.debug('Adding Entry: ' + fullPath);
            zipEntry = new java.util.zip.ZipEntry(fullPath);
            zipEntry.setSize(file.length());
            zipEntry.setTime((new java.util.Date()).getTime());
            zipFileStream.putNextEntry(zipEntry);
            
            while ((length = inputStream.read(bytes)) >= 0) {
               zipFileStream.write(bytes, 0, length);
            }
            
            zipFileStream.closeEntry();
            inputStream.close()
            currentZipFileSize += zipEntry.getCompressedSize();
         }
      }
   } finally {
      if (zipFileStream !== null) {
         zipFileStream.finish();
         zipFileStream.flush();
         zipFileStream.close();
      }
   }
}

answered Jan 6, 2020 by brandon-w-8204 (33,270 points)
...