thecfguy

A Unique Developer

Add file into zip from URL in Coldfusion

For one of our client had requirement to download photos in zip format and it was working file with cfzip tag. Although I have some performance issue with cfzip tag as cfzip doesn’t allow you to zip with list of files. We can create zip for whole folder, add single file but can’t have ability to add list of files at single instance. In my case I have around 50 images which I need to add into zip file and I have only one way to do so is adding one by one file. I was looking for alternative solution for creating zip which gives faster performance with adding file list.

Now here is different story, recently we have decided to move our archived photos on cloud server because of billions of images causing disk space issue. We have two kinds of photos in our application, one is on our file server and physically accessible so easy to add into zip file using cfzip and other on cloud server which give us URL to access those photos. Only way for me to add into zip that download files from cloud and store on application server and add into zip. I already have performance issue with cfzip for photos stored in same server and downloading photos make it much slower. Finally I have decided to build custom code using java zip library.

After googling I found coldfusion code which let you create zip file using java zip library (thanks to Artur Kordowski)which let me add files in zip by file list but again it will not let you add file from URL. I use cfhttp to retrieve image from cloud which return ByteArrayOutputStream object which can be added easily into zip code component.  Below is fully functional code to add file from URL to zip component.

<cfset zipFilePath = expandPath('./test.zip') /><cfset images = "http://t2.gstatic.com/images?q=tbn:_ruOuQ2EjL3wOM:http://www.flash-slideshow-maker.com/images/help_clip_image020.jpg,http://t0.gstatic.com/images?q=tbn:--IQZoA0t4jdOM:http://www.dynamicdrive.com/dynamicindex4/lightbox2/flower.jpg,http://t3.gstatic.com/images?q=tbn:7i1D2KAZcCd8yM:http://www.flash-slideshow-maker.com/images/help_clip_image004.jpg" /><cfscript>    /* Create Objects */    ioOutput    = CreateObject("java","java.io.FileOutputStream");    zipFile     = CreateObject("java","java.util.zip.ZipFile");    zipEntry    = CreateObject("java","java.util.zip.ZipEntry");    zipInput    = CreateObject("java","java.util.zip.ZipInputStream");    zipOutput   = CreateObject("java","java.util.zip.ZipOutputStream");        ioOutput.init(zipFilePath);    zipOutput.init(ioOutput);    zipOutput.setLevel(9);</cfscript> <cfloop list="#images#" index="uri">    <cfset filename= listlast(uri,"/") />    <cfhttp url="#uri#" method="get">    <cfset objByteIO = cfhttp.filecontent />    <cfscript>        flag = true;        path = uri;        entryFile = filename;                //  Skip if entry with the same name already exsits        try        {            zipEntry.init(entryFile);            zipOutput.putNextEntry(zipEntry);            objByteIO.toByteArray();            zipOutput.write(objByteIO.toByteArray(), 0, objByteIO.size());            zipOutput.closeEntry();        }        catch(java.util.zip.ZipException ex)        { skip = "yes"; }    </cfscript> </cfloop><cfscript>zipOutput.close();</cfscript>

NOTE: Above code will work only when cfhttp returns ByteArrayOutputStream, in other case you may need to modify as per need.