<cfscript> // The data directory has a mixture of Images (which are already persisted using a // compressed file-format) and large HTML files (which can be compressed). dataDirectory = expandPath( "./data" ); // ------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------- // // First, let's test the performance and outcome of the zip CLI when we use NO // COMPRESSION at all. This will store the files in an archive, but will not attempt // to safe any file-size. timer label = "No Compression (-0)" type = "outline" { archiveFilePath = expandPath( "./output/no-compression.zip" ); zipOutput = executeZipFromDirectory( dataDirectory, [ // Don't use any compression. This will be the fastest approach, but will // not result in any file-size advantage. "-0", // Recurse the input directory. "--recurse-paths", // Define the OUTPUT file path for the generated zip. archiveFilePath, // Define the INPUT file - NOTE that this path is RELATIVE TO THE WORKING // DIRECTORY! By using a relative directory, it allows us to generate a // ZIP file in which the relative paths become the entries in the // resultant archive. "./" ] ); echo( "File size: " & getFileSize( archiveFilePath ) ); echo( "<pre>" & zipOutput & "</pre>" ); } // Next, let's test the default behavior of the zip CLI. This uses a compression // setting of -6, which will attempt to compress all files. timer label = "Default Compression (-6)" type = "outline" { archiveFilePath = expandPath( "./output/default-compression.zip" ); zipOutput = executeZipFromDirectory( dataDirectory, [ // Recurse the input directory. "--recurse-paths", // Define the OUTPUT file path for the generated zip. archiveFilePath, // Define the INPUT file - NOTE that this path is RELATIVE TO THE WORKING // DIRECTORY! By using a relative directory, it allows us to generate a // ZIP file in which the relative paths become the entries in the // resultant archive. "./" ] ); echo( "File size: " & getFileSize( archiveFilePath ) ); echo( "<pre>" & zipOutput & "</pre>" ); } // And, finally, let's test the performance and outcome of the zip CLI when we use // the default compression, but tell the CLI to store any IMAGE FILES WITHOUT // COMPRESSION. This will include images in the archive, but will not attempt to // improve upon the already-compressed file-formats. timer label = "Mixed Compression (-6 + suffixes)" type = "outline" { archiveFilePath = expandPath( "./output/mixed-compression.zip" ); // We are going to tell the zip CLI to skip compression for files with the given // set of file-extensions. This uses a colon-delimited list of extensions. // -- // CAUTION: Unfortunately, these suffix values are CASE-SENSITIVE. suffixes = [ ".gif", ".jpeg", ".jpg", ".png" ].toList( ":" ); zipOutput = executeZipFromDirectory( dataDirectory, [ // Recurse the input directory. "--recurse-paths", // Define which files will be archived using the STORAGE method (no // compression) instead of DEFLATE. "--suffixes #suffixes#", // Define the OUTPUT file path for the generated zip. archiveFilePath, // Define the INPUT file - NOTE that this path is RELATIVE TO THE WORKING // DIRECTORY! By using a relative directory, it allows us to generate a // ZIP file in which the relative paths become the entries in the // resultant archive. "./" ] ); echo( "File size: " & getFileSize( archiveFilePath ) ); echo( "<pre>" & zipOutput & "</pre>" ); } // ------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------- // /** * I execute the zip command-line utility from the given WORKING DIRECTORY using the * given arguments. If error-output is returned from the utility, an error with the * details is thrown. * * @workingDirectory I am the working directory from which to execute the zip command. * @zipArguments I am the command-line arguments for zip. */ public string function executeZipFromDirectory( required string workingDirectory, required array zipArguments ) { // The Shell Script that's going to proxy the ZIP command is expecting the // working directory to be the first argument. As such, let's create a normalized // set of arguments for our proxy that contains the working directory first, // followed by the rest of the commands. var normalizedArguments = [ workingDirectory ] .append( "zip" ) .append( zipArguments, true ) ; execute name = expandPath( "./execute_from_directory.sh" ) arguments = normalizedArguments.toList( " " ) variable = "local.successOutput" errorVariable = "local.errorOutput" timeout = 30 terminateOnTimeout = true ; if ( len( errorOutput ?: "" ) ) { throw( type = "ZipFromDirectoryError", message = "The zip command-line proxy returned error output.", detail = "Error: #errorOutput#", extendedInfo = "Working directory: #workingDirectory#, Command-line arguments: #serializeJson( zipArguments )#" ); } return( successOutput ?: "" ); } /** * I return a string representing the byte-size of the given file. * * @filepath I am the file to inspect. */ public string function getFileSize( required string filepath ) { return( numberFormat( fileInfo( filepath ).size ) ); } </cfscript>