View Javadoc
1 package org.apache.turbine.util.upload; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.io.BufferedInputStream; 58 import java.io.BufferedOutputStream; 59 import java.io.ByteArrayInputStream; 60 import java.io.ByteArrayOutputStream; 61 import java.io.File; 62 import java.io.FileInputStream; 63 import java.io.FileOutputStream; 64 import java.io.IOException; 65 import java.io.InputStream; 66 import java.io.OutputStream; 67 import java.io.UnsupportedEncodingException; 68 import javax.activation.DataSource; 69 import org.apache.turbine.services.uniqueid.TurbineUniqueId; 70 import org.apache.turbine.services.upload.TurbineUpload; 71 72 /*** 73 * <p> This class represents a file that was received by Turbine using 74 * <code>multipart/form-data</code> POST request. 75 * 76 * <p> After retrieving an instance of this class from the {@link 77 * org.apache.turbine.util.ParameterParser ParameterParser} (see 78 * {@link org.apache.turbine.util.ParameterParser#getFileItem(String) 79 * ParameterParser.getFileItem(String)} and {@link 80 * org.apache.turbine.util.ParameterParser#getFileItems(String) 81 * ParameterParser.getFileItems(String)}) you can use it to acces the 82 * data that was sent by the browser. You may either request all 83 * contents of file at once using {@link #get()} or request an {@link 84 * java.io.InputStream InputStream} with {@link #getStream()} and 85 * process the file without attempting to load it into memory, which 86 * may come handy with large files. 87 * 88 * Implements the javax.activation.DataSource interface (which allows 89 * for example the adding of a FileItem as an attachment to a multipart 90 * email). 91 * 92 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a> 93 * @author <a href="mailto:sean@informage.net">Sean Legassick</a> 94 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 95 * @version $Id: FileItem.java,v 1.6 2002/07/11 16:53:19 mpoeschl Exp $ 96 */ 97 public class FileItem implements DataSource 98 { 99 /*** 100 * The maximal size of request that will have it's elements stored 101 * in memory. 102 */ 103 public static final int DEFAULT_UPLOAD_SIZE_THRESHOLD = 10240; 104 105 /*** The original filename in the user's filesystem. */ 106 protected String fileName; 107 108 /*** 109 * The content type passed by the browser or <code>null</code> if 110 * not defined. 111 */ 112 protected String contentType; 113 114 /*** Cached contents of the file. */ 115 protected byte[] content; 116 117 /*** Temporary storage location. */ 118 protected File storeLocation; 119 120 /*** Temporary storage for in-memory files. */ 121 protected ByteArrayOutputStream byteStream; 122 123 124 /*** 125 * Constructs a new <code>FileItem</code>. 126 * 127 * <p>Use {@link #newInstance(String,String,String,int)} to 128 * instantiate <code>FileItems</code>. 129 * 130 * @param fileName The original filename in the user's filesystem. 131 * @param contentType The content type passed by the browser or 132 * <code>null</code> if not defined. 133 */ 134 protected FileItem(String fileName, String contentType) 135 { 136 this.fileName = fileName; 137 this.contentType = contentType; 138 } 139 140 /*** 141 * Returns the original filename in the user's filesystem. 142 * (implements DataSource method) 143 * 144 * @return The original filename in the user's filesystem. 145 */ 146 public String getName() 147 { 148 return getFileName(); 149 } 150 151 /*** 152 * Returns the original filename in the user's filesystem. 153 * 154 * @return The original filename in the user's filesystem. 155 */ 156 public String getFileName() 157 { 158 return fileName; 159 } 160 161 /*** 162 * Returns the content type passed by the browser or 163 * <code>null</code> if not defined. (implements 164 * DataSource method). 165 * 166 * @return The content type passed by the browser or 167 * <code>null</code> if not defined. 168 */ 169 public String getContentType() 170 { 171 return contentType; 172 } 173 174 /*** 175 * Provides a hint if the file contents will be read from memory. 176 * 177 * @return <code>True</code> if the file contents will be read 178 * from memory. 179 */ 180 public boolean inMemory() 181 { 182 return (content != null || byteStream != null); 183 } 184 185 /*** 186 * Returns the size of the file. 187 * 188 * @return The size of the file. 189 */ 190 public long getSize() 191 { 192 if (storeLocation != null) 193 { 194 return storeLocation.length(); 195 } 196 else if (byteStream != null) 197 { 198 return byteStream.size(); 199 } 200 else 201 { 202 return content.length; 203 } 204 } 205 206 /*** 207 * Returns the contents of the file as an array of bytes. If the 208 * contents of the file were not yet cached int the memory, they 209 * will be loaded from the disk storage and chached. 210 * 211 * @return The contents of the file as an array of bytes. 212 */ 213 public byte[] get() 214 { 215 if (content == null) 216 { 217 if (storeLocation != null) 218 { 219 content = new byte[(int) getSize()]; 220 try 221 { 222 FileInputStream fis = new FileInputStream(storeLocation); 223 fis.read(content); 224 } 225 catch (Exception e) 226 { 227 content = null; 228 } 229 } 230 else 231 { 232 content = byteStream.toByteArray(); 233 byteStream = null; 234 } 235 } 236 return content; 237 } 238 239 /*** 240 * Returns the contents of the file as a String, using default 241 * encoding. This method uses {@link #get()} to retrieve the 242 * contents of the file. 243 * 244 * @return The contents of the file. 245 */ 246 public String getString() 247 { 248 return new String(get()); 249 } 250 251 /*** 252 * Returns the contents of the file as a String, using specified 253 * encoding. This method uses {@link #get()} to retireve the 254 * contents of the file.<br> 255 * 256 * @param encoding The encoding to use. 257 * @return The contents of the file. 258 * @exception UnsupportedEncodingException. 259 */ 260 public String getString( String encoding ) 261 throws UnsupportedEncodingException 262 { 263 return new String(get(), encoding); 264 } 265 266 /*** 267 * Returns an {@link java.io.InputStream InputStream} that can be 268 * used to retrieve the contents of the file. (implements DataSource 269 * method) 270 * 271 * @return An {@link java.io.InputStream InputStream} that can be 272 * used to retrieve the contents of the file. 273 * @exception Exception, a generic exception. 274 */ 275 public InputStream getInputStream() 276 throws IOException 277 { 278 return getStream(); 279 } 280 281 /*** 282 * Returns an {@link java.io.InputStream InputStream} that can be 283 * used to retrieve the contents of the file. 284 * 285 * @return An {@link java.io.InputStream InputStream} that can be 286 * used to retrieve the contents of the file. 287 * @exception Exception, a generic exception. 288 */ 289 public InputStream getStream() 290 throws IOException 291 { 292 if (content == null) 293 { 294 if (storeLocation != null) 295 { 296 return new FileInputStream(storeLocation); 297 } 298 else 299 { 300 content = byteStream.toByteArray(); 301 byteStream = null; 302 } 303 } 304 return new ByteArrayInputStream(content); 305 } 306 307 /*** 308 * Returns the {@link java.io.File} objects for the FileItems's 309 * data temporary location on the disk. Note that for 310 * <code>FileItems</code> that have their data stored in memory 311 * this method will return <code>null</code>. When handling large 312 * files, you can use {@link java.io.File#renameTo(File)} to 313 * move the file to new location without copying the data, if the 314 * source and destination locations reside within the same logical 315 * volume. 316 * 317 * @return A File. 318 */ 319 public File getStoreLocation() 320 { 321 return storeLocation; 322 } 323 324 /*** 325 * Removes the file contents from the temporary storage. 326 */ 327 protected void finalize() 328 { 329 if (storeLocation != null && storeLocation.exists()) 330 { 331 storeLocation.delete(); 332 } 333 } 334 335 /*** 336 * Returns an {@link java.io.OutputStream OutputStream} that can 337 * be used for storing the contents of the file. 338 * (implements DataSource method) 339 * 340 * @return an {@link java.io.OutputStream OutputStream} that can be 341 * used for storing the contensts of the file. 342 * @exception IOException. 343 */ 344 public OutputStream getOutputStream() 345 throws IOException 346 { 347 if (storeLocation == null) 348 { 349 return byteStream; 350 } 351 else 352 { 353 return new FileOutputStream(storeLocation); 354 } 355 } 356 357 /*** 358 * Instantiates a FileItem. It uses <code>requestSize</code> to 359 * decide what temporary storage approach the new item should 360 * take. The largest request that will have its items cached in 361 * memory can be configured in 362 * <code>TurbineResources.properties</code> in the entry named 363 * <code>file.upload.size.threshold</code> 364 * 365 * @param path A String. 366 * @param name The original filename in the user's filesystem. 367 * @param contentType The content type passed by the browser or 368 * <code>null</code> if not defined. 369 * @param requestSize The total size of the POST request this item 370 * belongs to. 371 * @return A FileItem. 372 */ 373 public static FileItem newInstance(String path, 374 String name, 375 String contentType, 376 int requestSize) 377 { 378 FileItem item = new FileItem(name, contentType); 379 if (requestSize > TurbineUpload.getSizeThreshold()) 380 { 381 String instanceName = TurbineUniqueId.getInstanceId(); 382 String fileName = TurbineUniqueId.getUniqueId(); 383 fileName = instanceName + "_upload_" + fileName + ".tmp"; 384 fileName = path + "/" + fileName; 385 item.storeLocation = new File(fileName); 386 item.storeLocation.deleteOnExit(); 387 } 388 else 389 { 390 item.byteStream = new ByteArrayOutputStream(); 391 } 392 return item; 393 } 394 395 /*** 396 * A convenience method to write an uploaded 397 * file to disk. The client code is not concerned 398 * whether or not the file is stored in memory, 399 * or on disk in a temporary location. They just 400 * want to write the uploaded file to disk. 401 * 402 * @param String full path to location where uploaded 403 * should be stored. 404 */ 405 public void write(String file) throws Exception 406 { 407 if (inMemory()) 408 { 409 FileOutputStream fout = null; 410 try 411 { 412 fout = new FileOutputStream(file); 413 fout.write(get()); 414 } 415 finally 416 { 417 if (fout != null) 418 { 419 fout.close(); 420 } 421 } 422 } 423 else if (storeLocation != null) 424 { 425 /* 426 * The uploaded file is being stored on disk 427 * in a temporary location so move it to the 428 * desired file. 429 */ 430 if (storeLocation.renameTo(new File(file)) == false) 431 { 432 BufferedInputStream in = null; 433 BufferedOutputStream out = null; 434 try 435 { 436 in = new BufferedInputStream( 437 new FileInputStream(storeLocation)); 438 out = new BufferedOutputStream(new FileOutputStream(file)); 439 byte[] bytes = new byte[2048]; 440 int s = 0; 441 while ((s = in.read(bytes)) != -1) 442 { 443 out.write(bytes, 0, s); 444 } 445 } 446 finally 447 { 448 try 449 { 450 in.close(); 451 } 452 catch (Exception e) 453 { 454 // ignore 455 } 456 try 457 { 458 out.close(); 459 } 460 catch (Exception e) 461 { 462 // ignore 463 } 464 } 465 } 466 } 467 else 468 { 469 /* 470 * For whatever reason we cannot write the 471 * file to disk. 472 */ 473 throw new Exception("Cannot write uploaded file to disk!"); 474 } 475 } 476 }

This page was automatically generated by Maven