001/* 002 * $HeadURL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/servlet/ZipFiles.java $ 003 * $Revision: 1105 $ 004 * $LastChangedDate: 2016-05-16 19:19:44 -0700 (Mon, 16 May 2016) $ 005 * $LastChangedBy: tgutwin $ 006 * Copyright (c) 2016 Tom B. Gutwin P.Eng. North Vancouver BC Canada 007 * 008 * This program is free software; you can redistribute it and/or 009 * modify it under the terms of the GNU General Public License 010 * as published by the Free Software Foundation; either version 3 011 * of the License, or any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; If not, see <http://www.gnu.org/licenses/>. 020 */ 021package ca.bc.webarts.servlet; 022 023import java.io.BufferedInputStream; 024import java.io.BufferedOutputStream; 025import java.io.File; 026import java.io.FileInputStream; 027import java.io.FileNotFoundException; 028import java.io.IOException; 029import java.util.ArrayList; 030import java.util.Enumeration; 031import java.util.List; 032import java.net.InetAddress; 033import java.net.UnknownHostException; 034import java.util.zip.ZipEntry; 035import java.util.zip.ZipOutputStream; 036 037import javax.servlet.ServletConfig; 038import javax.servlet.ServletContext; 039import javax.servlet.ServletException; 040import javax.servlet.ServletOutputStream; 041import javax.servlet.http.HttpServlet; 042import javax.servlet.http.HttpServletRequest; 043import javax.servlet.http.HttpServletResponse; 044 045import com.oreilly.servlet.ParameterParser; 046import com.oreilly.servlet.ParameterNotFoundException; 047import com.oreilly.servlet.ServletUtils; 048 049 050/** 051 * <h1>Downloading single or Multiple Files As Zip file.</h1> 052 * 053 * <h2>3 steps to implement</h2><ol><li>add this class to WEB-INF/classes</li> 054 * <li>add the following to your web.xml file<pre> 055 <servlet> 056 <servlet-name>ZipFiles</servlet-name> 057 <servlet-class>ca.bc.webarts.servlet.ZipFiles</servlet-class> 058 </servlet> 059 <servlet-mapping> 060 <servlet-name>ZipFiles</servlet-name> 061 <url-pattern>/zipfiles/*</url-pattern> 062 </servlet-mapping> 063 </servlet> 064 </pre></li><li>Add the URL link to your webpage (html or jsp). The syntax (based on the mapping you setup in the web.xml) 065 * and parameters are as follows:<ul><li>http://<yourWebServerAddress>/<yourWebAppContextName><b>/zipfiles/?filename=<fileToZip>&dirname=<suDirWhereFileLives></b></li> 066 * <li> example: http://warp4.webarts.bc.ca/tunes/ZipFiles/?filename=AThousandSuns_03-Radiance.ogg&dirname=mythTunes/LinkinPark/AThousandSuns</li> 067 * <li> NOTE: filename param is OPTIONAL. if NOT provided, this servlet will zip all files in the dirname.</li> 068 * </ul> 069 * </li> 070 * </ol> 071 * <h3> This code is Copyright © 2016 Tom B. Gutwin P.Eng. North Vancouver BC Canada,</h3><h4>and relesed under the <a href="http://www.gnu.org">GNU</a> 072 * <a href="http://www.gnu.org/licenses/licenses.html#GPL">General Public License (GNU GPL)</a>.</h4> 073 */ 074public class ZipFiles extends HttpServlet 075{ 076 077 private static final long serialVersionUID = -2767248383788052391L; 078 /** Class constant. **/ 079 protected static final String className_ = "ZipFiles"; 080 private final static String SYSTEM_FILE_SEPERATOR = File.separator; 081 /** Version String. */ 082 private final static String SERVLET_VERSION = "0.01_[$Rev: 1105 $]"; 083 084 /** Build String. (yymmddhhss) */ 085 private final static String BUILD_TAG = "161015143718"; 086 087 private static String webServerHostName_ = "warp4.webarts.bc.ca"; 088 089 private boolean debugOut_ = false; 090 /** flag if the parms have specified a file (true) or a dir (false) to zip. **/ 091 private boolean fileZip_ = true; 092 /** flag if the parms are valid. **/ 093 private boolean validParms_ = true; 094 095 /** controls if extra info is dumped to system.out. **/ 096 private String debugOut = ""; 097 /** not used. **/ 098 private String browserName = ""; 099 /** not used. **/ 100 private String browserVersion = ""; 101 102 /** Servlet parameter to specify the specific file(name) to zip up and return. **/ 103 private String filename = ""; 104 /** Servlet parameter to specify the specific directory to zip up and return; OR if a filename is ALSO specified, the dire where the file exists. **/ 105 private String dirname = ""; 106 private String someParamYouWannaSet_ = ""; 107 108 /** 109 * Gets the ServletInfo attribute of this servlet 110 * 111 * @return The ServletInfo value 112 */ 113 public String getServletInfo() 114 { 115 final String methodName = "getServletInfo"; 116 return "WebARTS Design ZipFiles servlet. Version:" + SERVLET_VERSION + 117 " Build:" + BUILD_TAG; 118 } 119 120 121 /** 122 * The one time servlet init stuff goes here. It sets the derbyDBDir based on the following prioritized varables: 123 * <ol><li>context init param: derbyDBDir</li><li>servlet init param (from web.xml): derbyDBDir</li> 124 * <li>default hardcoded variable: derbyDBDir</li></ol>If defined in multiple places, the higher priority item will 125 * be used. 126 **/ 127 public void init() 128 { 129 System.out.println("\n~~~~~~~~\n~~~~~~~~\nInitializing ca.bc.webarts.servlet.ZipFiles\n~~~~~~~~\n~~~~~~~~"); 130 131 boolean notFoundInit = true; 132 boolean notFoundContext = true; 133 java.util.Enumeration <String> initEnum = getInitParameterNames(); 134 for (; notFoundInit && initEnum.hasMoreElements();) 135 { 136 if(initEnum.nextElement().equals("someParamYouWannaSet")) 137 { 138 notFoundInit = false; 139 /* Do something with the init param */ 140 someParamYouWannaSet_ = getInitParameter("someParamYouWannaSet"); 141 System.out.println("\n~~~~~~~~\n INIT ServletParam: someParamYouWannaSet="+someParamYouWannaSet_); 142 } 143 } 144 145 //also check context 146 initEnum = getServletConfig().getServletContext().getInitParameterNames(); 147 for (; notFoundContext && initEnum.hasMoreElements();) 148 { 149 if(initEnum.nextElement().equals("someParamYouWannaSet")) 150 { 151 notFoundContext = false; 152 /* Do something with the init param */ 153 someParamYouWannaSet_ = getServletConfig().getServletContext().getInitParameter("baseDir"); 154 System.out.println("\n~~~~~~~~\n INIT ContextParam: someParamYouWannaSet="+someParamYouWannaSet_); 155 } 156 } 157 158 if(notFoundInit && notFoundContext ) 159 { 160 /* Set the default values */ 161 //eagleDBDir_ = pEye_.getDerbyDBDir(); 162 } 163 164 try 165 { 166 webServerHostName_ = InetAddress.getLocalHost().getHostName(); 167 } 168 catch (UnknownHostException ex) 169 { 170 webServerHostName_ = "warp4.webarts.bc.ca"; 171 } 172 } 173 174 175 /** Override to close Things up. **/ 176 public void destroy() 177 { 178 super.destroy(); 179 } 180 181 182 /** Parses any defined servlet params into the defined class vars. **/ 183 private void parseParams(HttpServletRequest req) 184 { 185 ParameterParser parser = new ParameterParser(req); 186 if(debugOut_) 187 { 188 System.out.println("\nRequest Params:"); 189 Enumeration<String> parmNames = req.getParameterNames(); 190 for (; parmNames.hasMoreElements();) 191 { 192 String currParamName = (String) parmNames.nextElement(); 193 System.out.println(" "+currParamName+"="+req.getParameter(currParamName)); 194 } 195 } 196 197 /* parse out the requeSystem.out.println("lastFmst params into class vars */ 198 debugOut = parser.getStringParameter("debugOut", ""); 199 browserName = parser.getStringParameter("clientBrowser",""); 200 browserVersion = parser.getStringParameter("clientBrowserVersion",""); 201 filename = parser.getStringParameter("filename",""); 202 dirname = parser.getStringParameter("dirname",""); 203 204 if(filename.equals("")) 205 { 206 fileZip_=false; 207 if(dirname.equals("")) validParms_=false; 208 } 209 210 if(debugOut_) { System.out.println(" filename="+filename+" dirname="+dirname );} 211 212 } 213 214 215 /** 216 * Initisalizes File only if it is directory.It is represented by the passed 217 * in String. 218 * 219 * @param s the directory name to init as a File 220 * @return An instatiated File object if the passed string is a dir, null 221 * if not 222 */ 223 private static File initDirFile(String s) 224 { 225 File retVal = null; 226 File dirFile = new File(s); 227 if (dirFile.isDirectory() && dirFile.canRead()) 228 { 229 retVal = dirFile; 230 } 231 return retVal; 232 } 233 234 235 /** 236 * Takes a dirname and lists the contained files in an ArrayList for easier processing. 237 * 238 * @param d the directory name to scan for Files 239 * @return An instatiated ArrayList object full of the contained files or null if invalid. 240 */ 241 private ArrayList <File> listDirFiles(String d) 242 { 243 ArrayList retVal = new ArrayList();; 244 File dirToList = initDirFile(d); 245 if (dirToList != null) 246 { 247 String[] files = dirToList.list(); 248 File tempFile; 249 250 //loop through all the files in the dir 251 for (int i = 0; i < files.length; i++) 252 { 253 tempFile = new File(d + File.separator + files[i]); 254 if (tempFile.isDirectory()) 255 { 256 // recurse on the subdirectory 257 if(debugOut_) System.out.println("Adding DIR to list " + d + File.separator + files[i]); 258 retVal.addAll(listDirFiles(d + File.separator + files[i])); 259 } 260 else 261 { 262 if(debugOut_) System.out.println("Adding to list " + d + File.separator + files[i]); 263 retVal.add(new File(d + File.separator + files[i])); 264 } 265 } 266 } 267 else 268 { 269 if(d!=null && !d.equals("")) 270 { 271 if(debugOut_) System.out.println("Adding to list: " + d ); 272 retVal.add(new File(d)); 273 } 274 else 275 retVal = null; 276 } 277 return retVal; 278 } 279 280 281 /** Servlet get processing method. **/ 282 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 283 { 284 parseParams(request); 285 286 ServletContext context = getServletConfig().getServletContext(); 287 String cPath = context.getRealPath("/"); 288 289 if(validParms_) 290 { 291 292 String zipFilename = (fileZip_? 293 filename.substring(0, 294 (filename.lastIndexOf(".")>0? 295 filename.lastIndexOf("."): 296 filename.length()))+".zip" 297 : dirname+".zip"); 298 299 ServletOutputStream out = response.getOutputStream(); 300 String conPath = request.getContextPath(); 301 302 if(debugOut_) 303 { 304 System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 305 System.out.println("ZipFiles.doGet debugOut="+debugOut); 306 System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 307 } 308 309 // Set the content type based to zip 310 response.setContentType("Content-type: text/zip"); 311 response.setHeader("Content-Disposition", "attachment; filename="+zipFilename); 312 313 // List of files to be downloaded 314 String fPath = cPath+File.separator+(dirname.equals("")?"":dirname+File.separator)+filename; 315 ArrayList <File> filesList = listDirFiles(fPath); 316 if(debugOut_) System.out.println("Searching for file in " + fPath); 317 318 if(filesList!=null) 319 { 320 321 ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(out)); 322 323 for (File file : filesList) 324 { 325 if(debugOut_) System.out.println("Adding to zip" + file.getName()); 326 zos.putNextEntry(new ZipEntry(file.getName())); 327 328 // Get the file 329 FileInputStream fis = null; 330 try 331 { 332 fis = new FileInputStream(file); 333 334 } 335 catch (FileNotFoundException fnfe) 336 { 337 // If the file does not exists, write an error entry instead of 338 // file 339 // contents 340 zos.write(("ERROR: could not find file " + file.getName()) .getBytes()); 341 zos.closeEntry(); 342 System.out.println("Could find file " + file.getAbsolutePath()); 343 continue; 344 } 345 346 BufferedInputStream fif = new BufferedInputStream(fis); 347 348 // Write the contents of the file 349 int data = 0; 350 while ((data = fif.read()) != -1) 351 { 352 zos.write(data); 353 } 354 fif.close(); 355 356 zos.closeEntry(); 357 System.out.println("Finished zipping file " + file.getName()); 358 } 359 360 zos.close(); 361 } 362 } 363 } 364}