Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 81364 invoked from network); 21 Jun 2010 08:30:16 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 21 Jun 2010 08:30:16 -0000 Received: (qmail 54777 invoked by uid 500); 21 Jun 2010 08:30:16 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 54661 invoked by uid 500); 21 Jun 2010 08:30:14 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 54641 invoked by uid 99); 21 Jun 2010 08:30:14 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 21 Jun 2010 08:30:14 +0000 X-ASF-Spam-Status: No, hits=-1750.3 required=10.0 tests=ALL_TRUSTED,AWL X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 21 Jun 2010 08:30:09 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0B33F23889C5; Mon, 21 Jun 2010 08:29:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r956490 [1/2] - in /commons/sandbox/commons-fileupload2: ./ .settings/ src/changes/ src/java/org/apache/commons/fileupload2/ src/java/org/apache/commons/fileupload2/disk/ src/java/org/apache/commons/fileupload2/impl/ src/java/org/apache/com... Date: Mon, 21 Jun 2010 08:29:23 -0000 To: commits@commons.apache.org From: jochen@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100621082924.0B33F23889C5@eris.apache.org> Author: jochen Date: Mon Jun 21 08:29:22 2010 New Revision: 956490 URL: http://svn.apache.org/viewvc?rev=956490&view=rev Log: Finished work on the test suite, first documentation draft. Added: commons/sandbox/commons-fileupload2/.settings/org.maven.ide.eclipse.prefs commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptor.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptorFactory.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletFileTracker.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/ServletFileTracker.java commons/sandbox/commons-fileupload2/src/site/apt/ commons/sandbox/commons-fileupload2/src/site/apt/customizing.apt commons/sandbox/commons-fileupload2/src/site/apt/index.apt commons/sandbox/commons-fileupload2/src/site/apt/streaming.apt commons/sandbox/commons-fileupload2/src/site/apt/using.apt commons/sandbox/commons-fileupload2/src/site/fml/ commons/sandbox/commons-fileupload2/src/site/fml/faq.fml Removed: commons/sandbox/commons-fileupload2/build-gump.xml commons/sandbox/commons-fileupload2/build.xml commons/sandbox/commons-fileupload2/gump.xml commons/sandbox/commons-fileupload2/maven.xml commons/sandbox/commons-fileupload2/project.properties commons/sandbox/commons-fileupload2/project.xml Modified: commons/sandbox/commons-fileupload2/.classpath commons/sandbox/commons-fileupload2/.project commons/sandbox/commons-fileupload2/pom.xml commons/sandbox/commons-fileupload2/src/changes/changes.xml commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/EventListener.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/StoredFileItem.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItem.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItemStore.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java commons/sandbox/commons-fileupload2/src/site/site.xml commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/ProgressListenerTest.java commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/SizesTest.java commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/StreamingTest.java Modified: commons/sandbox/commons-fileupload2/.classpath URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/.classpath?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/.classpath (original) +++ commons/sandbox/commons-fileupload2/.classpath Mon Jun 21 08:29:22 2010 @@ -1,8 +1,8 @@ - - - + + + Modified: commons/sandbox/commons-fileupload2/.project URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/.project?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/.project (original) +++ commons/sandbox/commons-fileupload2/.project Mon Jun 21 08:29:22 2010 @@ -11,12 +11,12 @@ - org.maven.ide.eclipse.maven2Builder + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + org.maven.ide.eclipse.maven2Builder Added: commons/sandbox/commons-fileupload2/.settings/org.maven.ide.eclipse.prefs URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/.settings/org.maven.ide.eclipse.prefs?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/.settings/org.maven.ide.eclipse.prefs (added) +++ commons/sandbox/commons-fileupload2/.settings/org.maven.ide.eclipse.prefs Mon Jun 21 08:29:22 2010 @@ -0,0 +1,9 @@ +#Mon Jun 07 12:00:59 CEST 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 Modified: commons/sandbox/commons-fileupload2/pom.xml URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/pom.xml?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/pom.xml (original) +++ commons/sandbox/commons-fileupload2/pom.xml Mon Jun 21 08:29:22 2010 @@ -204,8 +204,8 @@ org.apache.james - apache-mime4j - 0.6 + apache-mime4j-core + 0.7-SNAPSHOT jar compile Modified: commons/sandbox/commons-fileupload2/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/changes/changes.xml?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/changes/changes.xml (original) +++ commons/sandbox/commons-fileupload2/src/changes/changes.xml Mon Jun 21 08:29:22 2010 @@ -37,424 +37,13 @@ The type attribute can be add,u Release Notes - Martin Cooper - - - Temporary files have not been deleted, if an error - occurred in FileUploadBase.parseRequest(); - - - Fixed example in MultipartStream Javadocs. - - - Ensured, that the ProgressListener is called for all - items. - - - Made the ProgressNotifier public. - - - Multiple documentation fixes. - - - Fixed the error message for FileSizeLimitExceededException - from "too many characters" to "too many bytes". - - - A FileSizeLimitExceededException does now contain the - file and field name of the item, which caused the problem. - - - - + - Upgrade to commons-io-1.4-SNAPSHOT, in order to use the new - FileCleaningTracker and fix issues with FileCleaner. - - - Made the MockHttpServletRequest comply to the servlet 2.4 specification - by applying - http://www.sourcelabs.com/dashboards/sash-1.2/patches/commons-fileupload-1.1-1/SUP-520.diff - - - Added support for accessing the file item headers. - - - A MalformedStreamException is now thrown, if the size of an items - headers exceeds HEADER_PART_SIZE_MAX; - - - DiskFileItem.toString() could throw an NPE. - - - Short files could cause an unexpected end of the item stream. - - - A FileSizeLimitExceededException was deferred until the complete - file has been uploaded. Additionally, the FileSizeLimitException - is now thrown immediately, if the attachments headers contain - a content-length value, which exceeds the configured limit. - - - Fixed a classpath problem when building with Sun JDK 1.3.1 - and Ant. + Rewrite, based on Apache Mime4J. - - - - Made Streams.asString static. - - - Eliminated duplicate code. - - - Added a streaming API. - - - Eliminated the necessity of a content-length header. - - - Eliminated the limitation of a maximum size for a single - header line. (The total size of all headers is already - limited, so there's no need for another limit.) - - - Added the ProgressListener, which allows to implement a - progress bar. - - - Added support for header continuation lines. - - - It is now possible to limit the actual file size and not - the request size. - - - Added the FileCleanerCleanup as an example for how to close - down the FileCleaner's reaper thread nicely. - - - A descriptive NPE is now thrown, if the FileItemFactory - has not been set. - - - - - - - Cache disk file item size when it is moved to a new location. - - - - File names were being inadvertently converted to lower case. - - - - - - - - Updates for FileUpload 1.1-RC1. - - - - Added release notes for FileUpload 1.1. - - - - Update the User Guide to document the "right" way of using FileUpload - 1.1, rather than the older, and thus deprecated, ways that are - compatible with FileUpload 1.0. - - - - Add this change log, including all changes since the Commons FileUpload - 1.0 release. - - - - Update Commons IO dependency to version 1.1. - - - - Add custom PMD configuration. - - - - Make inner exception classes static, which they should have been all - along. - - - - Fix Checkstyle warnings. - - - - Remove Javadoc warnings. - - - - Build updates: -
    -
  • - Include NOTICE.txt in the jar file and distributions. -
  • -
  • - Include xdocs in source distribution. -
  • -
  • - Create MD5 checksums for distributions. -
  • -
-
- - - Add custom Checkstyle configuration. - - - - Update dependencies in POM, and add comments and scope. - - - - Standardise on @throws instead of having a mixture of that and - @exception. - - - - Make DiskFileItem serializable. Thanks to Niall Pemberton for the - suggestion and patch. - - - - Make the temporary file names unique across class loaders, not just - within them, by including a UID in the file name. - - - - Include the actual and permitted sizes in both the exception message - and the exception itself. - - - - If an explicit header encoding is not specified, use the one from the - appropriate context (i.e. ServletRequest or ActionRequest). - - - - Add getCharacterEncoding to the request context. - - - - Null check and case insensitivity fixes. - - - - Web site updates: -
    -
  • - Add detail pages for Source Repository and Issue Tracking, based on - those for IO and Validator. -
  • -
  • - Improvements to FileUpload home page, based on similar recent - changes to IO and Validator home pages. -
  • -
  • - The Bugzilla component name has a space in it. Fix the URLs. -
  • -
  • - Add an FAQ page, using the Maven plugin to generate it. -
  • -
-
- - - Fixes to POMs - - - - Setting source and target for Java 1.3 - - - - Fix typos in Javadoc code examples. - - - - Fix typos in exception messages. - - - - Obtain request content type from container instead of headers. - - - - New mock objects from Jetspeed-2, and new FileUpload test cases. - - - - added toString() methods - - - - Fix up the existing package.html file and add new ones for the newly - introduced packages. Fairly minimal, but with a link to the user guide. - - - - Substantial refactoring and additions: -
    -
  • - The core package is now independent of servlet / portlet / other - distinctions, as well as persistence schemes, other than deprecated - classes and methods retained for backwards compatibility. -
  • -
  • - Servlet specific functionality has been moved to a new 'servlet' - package. Existing users should migrate to this as soon as possible, - since the servlet specific functionality in the generic package - will be removed in the release after FileUpload 1.1. -
  • -
  • - Support for portlets (JSR 168) has been added, in a new 'portlet' - package. This is not well tested at this point, and feedback would - be very much appreciated. (This also resolves bug #23620.) -
  • -
  • - The disk-based file item implementation has been moved into a 'disk' - package, and renamed from Default* to Disk* to reflect what it - really is. The Default* classes have been retained in the top level - package for backwards compatibility, but are now deprecated, and - will be removed in the release after FileUpload 1.1. -
  • -
  • - The isMultipartRequest method is an unfortunate casualty of this - refactoring. That method should really be moved to ServletFileUpload, - but since the method is static, it can only exist in either - FileUploadBase or ServletFileUpload. Backwards compatibility dictates - the former for now, but the latter is the desired state, which - implies some future breakage. Fair warning... -
  • -
-
- - - Specify the encoding (ISO-8859-1) when converting the boundary to a - byte array. - - - - Convert to Sun coding guidelines. - - - - DeferredFileOutputStream moved to Commons IO. - - - - Workaround for Mac IE5 bug. Thanks to Justin Sampson for the patch and - tests for this vexing issue. - - - - Handle unquoted header parameters. - - - - Some documentation on interaction with virus scanners. - - - - More unit tests from Justin Sampson. - - - - Use FileCleaner from Commons IO to clean up temp files, rather than - File.deleteOnExit(), which can cause serious problems in long-running - processes. - - - - Check that HTTP method is POST as part of multipart check. - - - - Switch to Commons IO version of DeferredFileOutputStream. Adding IO as - a dependency will allow us to take advantage of other classes in that - component to fix additional FileUpload bugs. - - - - handle quoted boundary specification. - - - - use case-independent comparisons for encoding types. - - - - Fix comments to avoid break iterator complaints. - - - - Fix typos in comments. - - - - Add support for character sets specified for individual parts. - - - - Change to Apache License 2.0 - - - - Correct the comment for the no-args constructor to reflect the fact - that a factory needs to be set before parsing uploads. - - - - Collapse some all but duplicated code. - - - - Fix example showing FileItem.write to use a File object. - - - - Check for null before attempting to close streams in write(). - - - - Correction to sample code in the docs. - - -
- - - - - - Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/EventListener.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/EventListener.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/EventListener.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/EventListener.java Mon Jun 21 08:29:22 2010 @@ -99,7 +99,8 @@ public interface EventListener { /** * Called to indicate that a new {@link FileItem} was found * and is being parsed. - * @return The number of bytes, after which {@link #parsingItem(FileUpload, UploadRequest, FileItem, long)} + * @return The number of bytes (between 0 and {@link Integer#MAX_VALUE}, + * after which {@link #parsingItem(FileUpload, UploadRequest, FileItem, long)} * should be called. May be {@link #NO_PARSING_ITEM_CALLS}, in * which case the method won't be invoked at all. * @see #parsingItem(FileUpload, UploadRequest, FileItem, long) @@ -145,7 +146,8 @@ public interface EventListener { * at all, because {@link #endItem(FileUpload, UploadRequest, FileItem, long)} will * be invoked immediately. However, you can rely on the fact that the * method won't be invoked more than 2 times. - * @return The number of bytes, after which {@link #parsingItem(FileUpload, UploadRequest, FileItem, long)} + * @return The number of bytes (between 0 and {@link Integer#MAX_VALUE}, + * after which {@link #parsingItem(FileUpload, UploadRequest, FileItem, long)} * should be called again. May be {@link #NO_PARSING_ITEM_CALLS}, in * which case no more invocations will happen for this file item. * @see #startItem(FileUpload, UploadRequest, FileItem) Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/StoredFileItem.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/StoredFileItem.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/StoredFileItem.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/StoredFileItem.java Mon Jun 21 08:29:22 2010 @@ -76,4 +76,11 @@ public interface StoredFileItem extends * @throws IOException An I/O error occurred while deleting the file item. */ void delete() throws FileUploadException, IOException; + + /** + * Returns, whether the file item is stored in external media + * (like file system, or in a database), or completely held in + * memory. + */ + boolean isInMemory(); } Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItem.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItem.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItem.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItem.java Mon Jun 21 08:29:22 2010 @@ -61,4 +61,8 @@ public class DiskFileItem extends Abstra file.delete(); file = null; } + + public boolean isInMemory() { + return false; + } } Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItemStore.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItemStore.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItemStore.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/disk/DiskFileItemStore.java Mon Jun 21 08:29:22 2010 @@ -5,9 +5,9 @@ import java.io.IOException; import org.apache.commons.fileupload2.FileItem; import org.apache.commons.fileupload2.FileItemStore; -import org.apache.commons.fileupload2.FileUploadException; import org.apache.commons.fileupload2.impl.MemoryCapableFileItemStore; import org.apache.commons.fileupload2.impl.WritableFileItem; +import org.apache.commons.io.FileCleaningTracker; /** @@ -16,6 +16,7 @@ import org.apache.commons.fileupload2.im */ public class DiskFileItemStore extends MemoryCapableFileItemStore { private File repository; + private FileCleaningTracker tracker; private boolean deletingOnExit = true; /** @@ -63,14 +64,62 @@ public class DiskFileItemStore extends M } protected File newFile() throws IOException { - final File f = File.createTempFile("fileUpload", null, getRepository()); + final File f = File.createTempFile("fileUpload", null, getRepository()); f.deleteOnExit(); return f; } @Override protected WritableFileItem newWritableFileItem(FileItem pFileItem) - throws FileUploadException, IOException { - return new DiskFileItem(pFileItem, newFile()); + throws IOException { + final File f = newFile(); + final DiskFileItem dfi = new DiskFileItem(pFileItem, f); + track(dfi, f); + return dfi; } + + private void track(final FileItem pFileItem, final File pFile) { + final FileCleaningTracker tr = getTracker(); + if (tr != null) { + tr.track(pFile, pFileItem); + } + } + + /** + * This method allows to explicitly request storing a file item to disk. + * By default, file items aren't necessarily written to disk, depending + * on the value of {@link #getThreshold()}. + */ + public File writeToFile(FileItem pFileItem) throws IOException { + if (pFileItem == null) { + throw new IllegalArgumentException("The FileItem must not be null."); + } + final DiskFileItem dfi; + if (pFileItem instanceof DiskFileItem) { + dfi = (DiskFileItem) pFileItem; + } else { + final File f = newFile(); + dfi = new DiskFileItem(pFileItem, f); + track(pFileItem, f); + } + return dfi.getFile(); + } + + /** + * Returns the {@link FileCleaningTracker}, which is responsible + * for automatic disposal of temporary files, which are no longer + * needed. + */ + public FileCleaningTracker getTracker() { + return tracker; + } + + /** + * Sets the {@link FileCleaningTracker}, which is responsible + * for automatic disposal of temporary files, which are no longer + * needed. + */ + public void setTracker(FileCleaningTracker pTracker) { + tracker = pTracker; + } } Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java Mon Jun 21 08:29:22 2010 @@ -13,11 +13,11 @@ import org.apache.commons.fileupload2.In import org.apache.commons.fileupload2.UploadRequest; import org.apache.commons.fileupload2.util.LimitedInputStream; import org.apache.james.mime4j.MimeException; -import org.apache.james.mime4j.descriptor.BodyDescriptor; -import org.apache.james.mime4j.descriptor.MaximalBodyDescriptor; -import org.apache.james.mime4j.parser.EntityStates; -import org.apache.james.mime4j.parser.MimeEntityConfig; -import org.apache.james.mime4j.parser.MimeTokenStream; +import org.apache.james.mime4j.stream.BodyDescriptor; +import org.apache.james.mime4j.stream.EntityStates; +import org.apache.james.mime4j.stream.MimeEntityConfig; +import org.apache.james.mime4j.stream.MimeTokenStream; +import org.apache.james.mime4j.stream.RecursionMode; /** @@ -34,6 +34,7 @@ public class FileItemIteratorImpl= 0) { + numBytesToParseForEvent -= pCount; + if (numBytesToParseForEvent > 0) { + return; + } + } + numBytesToParseForEvent = listener.parsingItem(fileUpload, request, fi, super.getCount()); + if (numBytesToParseForEvent < EventListener.NO_PARSING_ITEM_CALLS || numBytesToParseForEvent > Integer.MAX_VALUE) { + throw new IllegalStateException("The value returned by parsingItem must be between 0 and " + Integer.MAX_VALUE); + } + } + + @Override + public int read() throws IOException { + final int result = super.read(); + if (result != -1) { + fireParsingItem(1); + } + return result; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + final int result = super.read(b, off, len); + if (result != -1 && result != 0) { + fireParsingItem(result); + } + return result; + } + + @Override + public long skip(long pCount) throws IOException { + final long result = super.skip(pCount); + if (result != -1 && result != 0) { + fireParsingItem(result); + } + return result; + } }; return itemStream; } @@ -202,7 +245,7 @@ public class FileItemIteratorImpl Integer.MAX_VALUE) { + throw new IllegalStateException("The value returned by startItem must be between 0 and " + Integer.MAX_VALUE); + } } return (FI) previousFileItem; } private void skip(LimitedInputStream pStream) throws IOException { while (!pStream.isClosed()) { - if (pStream.skip(Integer.MAX_VALUE) == -1) { + pStream.skip(Integer.MAX_VALUE); + if (pStream.read() == -1) { pStream.close(); } } Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptor.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptor.java?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptor.java (added) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptor.java Mon Jun 21 08:29:22 2010 @@ -0,0 +1,66 @@ +package org.apache.commons.fileupload2.impl; + +import java.util.Collections; +import java.util.Map; + +import org.apache.james.mime4j.MimeException; +import org.apache.james.mime4j.codec.DecodeMonitor; +import org.apache.james.mime4j.stream.BodyDescriptor; +import org.apache.james.mime4j.stream.DefaultBodyDescriptor; +import org.apache.james.mime4j.stream.MutableBodyDescriptor; +import org.apache.james.mime4j.stream.RawField; +import org.apache.james.mime4j.util.MimeUtil; + + +/** + * FileUpload specific implementation of {@link MutableBodyDescriptor}. + */ +public class FileUploadBodyDescriptor extends DefaultBodyDescriptor { + private Map contentDispositionParameters; + + /** + * Creates a new instance with the given monitor settings. + */ + public FileUploadBodyDescriptor(DecodeMonitor pMonitor) { + this(null, pMonitor); + } + + /** + * Creates a new instance with the given parent and monitor settings. + */ + public FileUploadBodyDescriptor(BodyDescriptor pParent, DecodeMonitor pMonitor) { + super(pParent, pMonitor); + } + + @Override + public void addField(RawField field) throws MimeException { + super.addField(field); + final String name = field.getName().trim().toLowerCase(); + final String value = field.getBody(); + if ("content-disposition".equals(name)) { + contentDispositionParameters = DefaultBodyDescriptor.getHeaderParams(value, getDecodeMonitor()); + } + } + + /** + * Returns the parameters of the "content-disposition" header. + */ + public Map getContentDispositionParameters() { + if (contentDispositionParameters == null) { + contentDispositionParameters = Collections.emptyMap(); + } + return contentDispositionParameters; + } + + /** + * Returns the file name, which is specified in the "content-disposition" header. + */ + public String getContentDispositionFilename() { + return getContentDispositionParameters().get(MimeUtil.PARAM_FILENAME); + } + + @Override + public MutableBodyDescriptor newChild() { + return new FileUploadBodyDescriptor(this, getDecodeMonitor()); + } +} Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptorFactory.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptorFactory.java?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptorFactory.java (added) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileUploadBodyDescriptorFactory.java Mon Jun 21 08:29:22 2010 @@ -0,0 +1,16 @@ +package org.apache.commons.fileupload2.impl; + +import org.apache.james.mime4j.codec.DecodeMonitor; +import org.apache.james.mime4j.stream.MutableBodyDescriptor; +import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory; + + +/** + * Implementation of {@link MutableBodyDescriptorFactory} with support + * for collecting headers. + */ +public class FileUploadBodyDescriptorFactory implements MutableBodyDescriptorFactory { + public MutableBodyDescriptor newInstance(DecodeMonitor pMonitor) { + return new FileUploadBodyDescriptor(pMonitor); + } +} Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java Mon Jun 21 08:29:22 2010 @@ -73,4 +73,8 @@ public class MemoryFileItem extends Abst public long getContentLength() { return buffer.length; } + + public boolean isInMemory() { + return true; + } } Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletFileTracker.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletFileTracker.java?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletFileTracker.java (added) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletFileTracker.java Mon Jun 21 08:29:22 2010 @@ -0,0 +1,20 @@ +package org.apache.commons.fileupload2.portlet; + +import javax.portlet.PortletContext; + +import org.apache.commons.fileupload2.servlet.ServletFileTracker; +import org.apache.commons.io.FileCleaningTracker; + + +/** + * This class is responsible for tracking temporary files, that + * must be removed later on. + */ +public class PortletFileTracker { + /** + * Returns this portlet contexts file tracker. + */ + public static FileCleaningTracker getFileTracker(PortletContext pContext) { + return (FileCleaningTracker) pContext.getAttribute(ServletFileTracker.KEY_FILE_CLEANER); + } +} Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/ServletFileTracker.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/ServletFileTracker.java?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/ServletFileTracker.java (added) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/ServletFileTracker.java Mon Jun 21 08:29:22 2010 @@ -0,0 +1,45 @@ +package org.apache.commons.fileupload2.servlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.io.FileCleaningTracker; + + +/** + * This class is responsible for tracking temporary files, that + * must be removed later on. + */ +public class ServletFileTracker implements ServletContextListener { + /** + * Key, which is used to store the {@link FileCleaningTracker file tracker} + * in the servlet context. + */ + public static final String KEY_FILE_CLEANER = ServletFileTracker.class.getName() + ".fileCleaner"; + + /** + * Returns this servlet contexts file tracker. + */ + public static FileCleaningTracker getFileTracker(ServletContext pContext) { + return (FileCleaningTracker) pContext.getAttribute(KEY_FILE_CLEANER); + } + + private static void setFileTracker(ServletContext pContext, FileCleaningTracker pFileCleaner) { + pContext.setAttribute(KEY_FILE_CLEANER, pFileCleaner); + } + + public void contextDestroyed(ServletContextEvent pEvent) { + final FileCleaningTracker cleaner = getFileTracker(pEvent.getServletContext()); + setFileTracker(pEvent.getServletContext(), null); + if (cleaner != null) { + cleaner.exitWhenFinished(); + } + } + + public void contextInitialized(ServletContextEvent pEvent) { + contextDestroyed(pEvent); + final FileCleaningTracker cleaner = new FileCleaningTracker(); + setFileTracker(pEvent.getServletContext(), cleaner); + } +} Modified: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java (original) +++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java Mon Jun 21 08:29:22 2010 @@ -134,6 +134,20 @@ public final class Streams { } /** + * This convenience method allows to read a {@link FileItem file items} + * content into a string. The file items encoding, if known, or the + * platforms default encoding is used to convert bytes into characters. + * @param pItem The file item to read. + */ + public static String asString(FileItem pItem) throws IOException { + final String encoding = pItem.getEncoding(); + if (encoding == null) { + return asString(pItem.getInputStream()); + } + return asString(pItem.getInputStream(), encoding); + } + + /** * This convenience method allows to read a * {@link FileItem file items} * content into a string. The platform's default character encoding @@ -210,4 +224,15 @@ public final class Streams { copy(pStream, baos, true); return baos.toByteArray(); } + + /** + * This convenience method allows to read a {@link FileItem file items} + * content into a byte array. + * @param pFileItem The file item to read + * @return The streams contents, as a byte array. + * @throws IOException An I/O error occurred. + */ + public static byte[] asByteArray(FileItem pFileItem) throws IOException { + return asByteArray(pFileItem.getInputStream()); + } } Added: commons/sandbox/commons-fileupload2/src/site/apt/customizing.apt URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/apt/customizing.apt?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/apt/customizing.apt (added) +++ commons/sandbox/commons-fileupload2/src/site/apt/customizing.apt Mon Jun 21 08:29:22 2010 @@ -0,0 +1,24 @@ +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + + ---------------------- + Customizing FileUpload + ---------------------- + +Customizing FileUpload + + TODO: Document usage of factories and subclassing for customization. Added: commons/sandbox/commons-fileupload2/src/site/apt/index.apt URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/apt/index.apt?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/apt/index.apt (added) +++ commons/sandbox/commons-fileupload2/src/site/apt/index.apt Mon Jun 21 08:29:22 2010 @@ -0,0 +1,57 @@ +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + + -------------------------- + About Commons Fileupload 2 + -------------------------- + +Commons FileUpload 2 + + The Commons <> 2 package makes it easy to add robust, + high-performance, file upload capability to your servlets and web + applications. + + FileUpload parses HTTP requests which conform to + {{{http://www.ietf.org/rfc/rfc1867.txt}RFC 1867}}, + "Form-based File Upload in HTML". That is, if an HTTP request is + submitted using the POST method, and with a content type of + "multipart/form-data", then FileUpload can parse that request, and + make the results available in a manner easily used by the caller. + +Documentation + + The following documentation is available: + + * {{{using.html}User Guide}} + * {{{streaming.html}Streaming API}} + * {{faq.html}Frequently Asked Questions}} + * {{{apidocs/index.html}JavaDoc API}} + * {{{project-reports.html}Project Reports}} + + You can also {{source-usage.html}browse}} the Subversion repository. + +Support + + The {{{mail-lists.html}Apache Commons mailing lists}} act as + the main support forum. The <> list is suitable for most library + usage queries. The <> list is intended for development discussion. + Please remember that the lists are shared between all commons components, + so prefix your e-mail subject line with <<<[fileupload]>>>. + + Issues may be reported via {{{issue-tracking.html}ASF JIRA}}. + + Added: commons/sandbox/commons-fileupload2/src/site/apt/streaming.apt URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/apt/streaming.apt?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/apt/streaming.apt (added) +++ commons/sandbox/commons-fileupload2/src/site/apt/streaming.apt Mon Jun 21 08:29:22 2010 @@ -0,0 +1,81 @@ +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + + ----------------- + The Streaming API + ----------------- + +The Streaming API + +* Why Streaming? + + The traditional, and more comfortable API, which is described in the + {{{using.html}User Guide}}, assumes, that file items must be stored + somewhere, before they are actually accessable by the user. This + approach is convenient, because it allows easy access to an items + contents. On the other hand, it is memory and time consuming. + + The streaming API allows you to trade a little bit of convenience for + optimal performance and and a low memory profile. Additionally, the + API is more lightweight, thus easier to understand. + +* How it works + + Again, the <<>> class is used for accessing the + form fields and fields in the order, in which they have been sent + by the client. However, the <<>>, or its main + implementation, the <<>>, is completely + ignored. + +* Parsing the request + + First of all, do not forget to ensure, that a request actually is a + a file upload request. This is typically done using the same static + method, which you already know from the traditional API. + +--------------------------------------------------------------------------- + // Check that we have a file upload request + boolean isMultipart = HttpServletUploadRequest.isMultipartContent(request); +--------------------------------------------------------------------------- + + Now we are ready to parse the request into its constituent items. Here's + how we do it: + +--------------------------------------------------------------------------- + // Create a new file upload handler + FileUpload upload = new FileUpload(); + + // Parse the request + HttpServletRequest req; + HttpServletUploadRequest request = new HttpServletUploadRequest(req); + FileItemIterator iter = upload.parse(request); + while (iter.hasNext()) { + FileItem item = iter.next(); + String name = item.getFieldName(); + if (item.isFormField()) { + System.out.println("Form field " + name + " with value " + + Streams.asString(item) + " detected."); + } else { + System.out.println("File field " + name + " with file name " + + item.getName() + " detected."); + // Process the input stream + InputStream istream = item.getInputStream(); + ... + } +--------------------------------------------------------------------------- + + That's all that's needed. Really! Added: commons/sandbox/commons-fileupload2/src/site/apt/using.apt URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/apt/using.apt?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/apt/using.apt (added) +++ commons/sandbox/commons-fileupload2/src/site/apt/using.apt Mon Jun 21 08:29:22 2010 @@ -0,0 +1,411 @@ +~~ Licensed to the Apache Software Foundation (ASF) under one +~~ or more contributor license agreements. See the NOTICE file +~~ distributed with this work for additional information +~~ regarding copyright ownership. The ASF licenses this file +~~ to you under the Apache License, Version 2.0 (the +~~ "License"); you may not use this file except in compliance +~~ with the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, +~~ software distributed under the License is distributed on an +~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +~~ KIND, either express or implied. See the License for the +~~ specific language governing permissions and limitations +~~ under the License. + + -------------------------- + Using Commons Fileupload 2 + -------------------------- + +Using Commons FileUpload 2 + + FileUpload can be used in a number of different ways, depending upon the + requirements of your application. In the simplest case, you will call a + single method to parse the servlet request, and then process the list of + items as they apply to your application. At the other end of the scale, + you might decide to customize FileUpload to take full control of the way + in which individual items are stored; for example, you might decide to + stream the content into a database. + + Here, we will describe the basic principles of FileUpload, and illustrate + some of the simpler - and most common - usage patterns. Customization of + FileUpload is described {{{customizing.html}elsewhere}}. + +How it works + + A file upload request comprises an ordered list of <> that + are encoded according to {{{http://www.ietf.org/rfc/rfc1867.txt}RFC 1867}}, + "Form-based File Upload in HTML". FileUpload can parse such a request + and provide your application with a list of the individual uploaded + items. Each such item implements the <> interface, + regardless of its underlying implementation. + + This page describes the traditional API of the commons fileupload + library. The traditional API is a convenient approach. However, for + ultimate performance, you might prefer the faster {{{streaming.html}Streaming + API}}. + + Each file item has a number of properties that might be of interest for + your application. For example, every item has a field name and a content + type, and can provide an <> to access its data. On the + other hand, you may need to process items differently, depending upon + whether the item is a regular form field - that is, the data came from + an ordinary text box or similar HTML field - or an uploaded file. The + <> interface provides the methods to make such a determination, + and to access the data in the most appropriate manner. + + FileUpload creates new file items using a <>. This is what + gives FileUpload most of its flexibility. The factory has ultimate control + over how each item is created and stored. The factory implementation that + currently ships with FileUpload stores the item's data in memory or + on disk, depending on the size of the item (i.e. bytes of data). However, + this behavior can be customized to suit your application. + +Servlets and Portlets + + Starting with version 1.1, FileUpload supports file upload requests in + both servlet and portlet environments. The usage is almost identical in + the two environments, so the remainder of this document refers only to + the servlet environment. + + If you are building a portlet application, the following are the two + distinctions you should make as you read this document: + + * Where you see references to the <> class, + substitute the <> class. + * Where you see references to the <> class, + substitute the <> class. + +Parsing the request + + Before you can work with the uploaded items, of course, you need to parse + the request itself. Ensuring that the request is actually a file upload + request is straightforward, but FileUpload makes it simplicity itself, by + providing a static method to do just that. + +--------------------------------------------------------------------------- + // Check that we have a file upload request + boolean isMultipart = HttpServletUploadRequest.isMultipartContent(request);]] +--------------------------------------------------------------------------- + + Now we are ready to parse the request into its constituent items. + +The simplest case + + The simplest usage scenario is the following: + + * Uploaded items should be retained in memory as long as they are reasonably + small. + * Larger items should be written to a temporary file on disk. + * Very large upload requests should not be permitted. + * The built-in defaults for the maximum size of an item to be retained in + memory, the maximum permitted size of an upload request, and the location + of temporary files are acceptable. + + Handling a request in this scenario couldn't be much simpler: + +--------------------------------------------------------------------------- + // Create a factory for disk-based file items + DiskFileItemStore store = new DiskFileItemStore(); + // Create a new file upload handler + FileUpload upload = new FileUpload(); + + // Parse the request + List items = store.parse(upload, request); +--------------------------------------------------------------------------- + + That's all that's needed. Really! + + The result of the parse is a <> of file items, each of which + implements the <>> interface. Processing these items + is discussed below. + +Exercising more control + + If your usage scenario is close to the simplest case, described above, + but you need a little more control, you can easily customize the + behavior of the upload handler or the file item factory or both. The + following example shows several configuration options: + +--------------------------------------------------------------------------- + // Create a factory for disk-based file items + DiskFileItemStore factory = new DiskFileItemStore(); + // Set factory constraints + factory.setThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + + // Create a new file upload handler + FileUpload upload = new FileUpload(); + // Set overall request size constraint + upload.setRequestSizeMax(yourMaxRequestSize); + + // Parse the request + List items = store.parse(upload, request); +--------------------------------------------------------------------------- + + Of course, each of the configuration methods is independent of the + others. + +--------------------------------------------------------------------------- + + Should you need further control over the parsing of the request, such + as storing the items elsewhere - for example, in a database - you will + need to look into {{{customizing.html}customizing}} FileUpload. + +Processing the uploaded items + + Once the parse has completed, you will have a <> of file items + that you need to process. In most cases, you will want to handle + file uploads differently from regular form fields, so you might process + the list like this: + +--------------------------------------------------------------------------- + // Process the uploaded items + Iterator iter = items.iterator(); + while (iter.hasNext()) { + StoredFileItem item = (StoredFileItem) iter.next(); + if (item.isFormField()) { + processFormField(item); + } else { + processUploadedFile(item); + } + } +--------------------------------------------------------------------------- + + For a regular form field, you will most likely be interested only in the + name of the item, and its <> value. The following example shows + how to access these: + +--------------------------------------------------------------------------- + // Process a regular form field + if (item.isFormField()) { + String name = item.getFieldName(); + String value = Streams.asString(item); + ... + } +--------------------------------------------------------------------------- + + For a file upload, there are several different things you might want to + know before you process the content. Here is an example of some of the + methods you might be interested in. + +--------------------------------------------------------------------------- + // Process a file upload + if (!item.isFormField()) { + String fieldName = item.getFieldName(); + String fileName = item.getFileName(); + String contentType = item.getContentType(); + boolean isInMemory = item.isInMemory(); + long sizeInBytes = item.getContentLength(); + ... +--------------------------------------------------------------------------- + + With uploaded files, you generally will not want to access them via + memory, unless they are small, or unless you have no other alternative. + Rather, you will want to process the content as a stream, or write the + entire file to its ultimate location. FileUpload provides simple means of + accomplishing both of these. + +--------------------------------------------------------------------------- + // Process a file upload + if (writeToFile) { + File uploadedFile = new DiskFileItemStore().writeToFile(item); + } else { + InputStream uploadedStream = item.getInputStream(); + ... + uploadedStream.close(); + } +--------------------------------------------------------------------------- + + Note that, in the default implementation of FileUpload, <<>> + will create a new file only, if that hasn't already be done. Actually + copying the data is only done if the file item is still held in memory. + + If you do need to access the uploaded data in memory, you need simply + call the <<>> method to obtain the data as an + array of bytes. + +--------------------------------------------------------------------------- + // Process a file upload in memory + byte[] data = Streams.asByteArray(item); +--------------------------------------------------------------------------- + +Resource cleanup + + This section applies only, if you are using the + {{{apidocs/org/apache/commons/fileupload2/disk/DiskFileItemStore.html}DiskFileItemStore}}. + In other words, it applies, if your uploaded files are written to + temporary files before processing them. + + Such temporary files can be deleted automatically, if they are no longer + used (more precisely, if the corresponding instance of <<>> + is garbage collected. This is done silently by the + <<>> class, which starts a + reaper thread. + + This reaper thread must be created and stopped, if it is no longer + needed. In a servlet environment, this is done by using a special + servlet context listener, called + {{{apidocs/org/apache/commons/fileupload2/servlet/ServletFileTracker.html}ServletFileTracker}}. + To do so, add a section like the following to your <<>>: + +--------------------------------------------------------------------------- + + ... + + + org.apache.commons.fileupload2.servlet.ServletFileTracker + + + ... + +--------------------------------------------------------------------------- + + Additionally, you must initialize your <<>> like + this: + +--------------------------------------------------------------------------- + ServletContext ctx = ...; /* Depends on your application, how to obtain + * the ServletContext. In a servlet application, + * there will be a possibility. + */ + DiskFileItemStore store = new DiskFileItemStore(); + store.setTracker(ServletFileTracker.getFileTracker(ctx)); +--------------------------------------------------------------------------- + + For a portlet environment, the same section in <<>> is required, + but your code would look like this: + +--------------------------------------------------------------------------- + PortletContext ctx = ...; /* Depends on your application, how to obtain + * the PortletContext. In a portlet application, + * there will be a possibility. + */ + DiskFileItemStore store = new DiskFileItemStore(); + store.setTracker(PortletFileTracker.getFileTracker(ctx)); +--------------------------------------------------------------------------- + + +Creating a DiskFileItemFactory + + The <<>> provides an instance of + <<>>. This instance must + be used when creating a {{{apidocs/org/apache/commons/fileupload2/disk/DiskFileItemFactory.html}DiskFileItemFactory}}. + + This should be done by calling a method like the following: + +--------------------------------------------------------------------------- + public static DiskFileItemFactory newDiskFileItemFactory(ServletContext pCtx, + File pRepository) { + FileCleaningTracker tracker = ServletFileTracker.getFileTracker(pCtx); + DiskFileItemFactory factory = new DiskFileItemFactory(); + factory.setRepository(pRepository); + factory.setTracker(tracker); + return factory; + } +--------------------------------------------------------------------------- + + +Disabling cleanup of temporary files + + To disable tracking of temporary files, you may set the + <<>> to null. Consequently, created files will no + longer be tracked. In particular, they will no longer be deleted + automatically. + + +Interaction with virus scanners + + Virus scanners running on the same system as the web container can cause + some unexpected behaviours for applications using FileUpload. This section + describes some of the behaviours that you might encounter, and provides + some ideas for how to handle them. + + The default implementation of FileUpload will cause uploaded items above + a certain size threshold to be written to disk. As soon as such a file is + closed, any virus scanner on the system will wake up and inspect it, and + potentially quarantine the file - that is, move it to a special location + where it will not cause problems. This, of course, will be a surprise to + the application developer, since the uploaded file item will no longer be + available for processing. On the other hand, uploaded items below that + same threshold will be held in memory, and therefore will not be seen by + virus scanners. This allows for the possibility of a virus being retained + in some form (although if it is ever written to disk, the virus scanner + would locate and inspect it). + + One commonly used solution is to set aside one directory on the system + into which all uploaded files will be placed, and to configure the virus + scanner to ignore that directory. This ensures that files will not be + ripped out from under the application, but then leaves responsibility for + virus scanning up to the application developer. Scanning the uploaded + files for viruses can then be performed by an external process, which + might move clean or cleaned files to an "approved" location, or by + integrating a virus scanner within the application itself. The details of + configuring an external process or integrating virus scanning into an + application are outside the scope of this document. + + +Watching progress + + If you expect really large file uploads, then it would be nice to report + to your users, how much is already received. Even HTML pages allow to + implement a progress bar by returning a multipart/replace response, + or something like that. + + Watching the upload progress may be done by supplying an event listener: + +--------------------------------------------------------------------------- + //Create an event listener + EventListener listener = new DefaultEventListener(){ + private final long APPROXIMATE_EVENT_INTERVAL = 100000; + private int num; + + public long startItem(FileUpload pFileUpload, UploadRequest pRequest, FileItem pItem) + throws IOException { + ++num; + System.out.println("Beginning to parse item " + num); + return APPROXIMATE_EVENT_INTERVAL; + } + + public long parsingItem(FileUpload pFileUpload, UploadRequest pRequest, FileItem pItem, + long pCurrentLength) throws IOException { + System.out.println("Still reading item " + num + ", " + pCurrentLength + + " bytes read so far."); + return APPROXIMATE_EVENT_INTERVAL; + } + + public void endItem(FileUpload pFileUpload, UploadRequest pRequest, FileItem pItem, + long pContentLength) + throws IOException { + System.out.println("Finished parsing item " + num + ", size = " + + pContentLength + " bytes."); + } + }; + // Install the event listener + FileUpload upload = new FileUpload(); + upload.setEventListener(listener); +--------------------------------------------------------------------------- + + Do yourself a favour and implement your first event listener just + like the above, but by changing the number APPROXIMATE_EVENT_INTERVAL + to a small value, like 1. This will show you a pitfall: The event + listener can be called quite frequently. Depending on the servlet + engine and other environment factors, it may be called for any + network packet, or even any single byte! In other words, your + progress listener may become a performance problem! + A typical solution might be, to reduce the event listeners activity + by increasing the value of APPROXIMATE_EVENT_INTERVAL. + +What's next + + Hopefully this page has provided you with a good idea of how to use + FileUpload in your own applications. For more detail on the methods + introduced here, as well as other available methods, you should refer + to the {{{apidocs/index.html}JavaDocs}}. + + The usage described here should satisfy a large majority of file upload + needs. However, should you have more complex requirements, FileUpload + should still be able to help you, with it's flexible + {{{customizing.html}customization}} capabilities. Added: commons/sandbox/commons-fileupload2/src/site/fml/faq.fml URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/fml/faq.fml?rev=956490&view=auto ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/fml/faq.fml (added) +++ commons/sandbox/commons-fileupload2/src/site/fml/faq.fml Mon Jun 21 08:29:22 2010 @@ -0,0 +1,126 @@ + + + + + + + General + + + + Why is parse(UploadRequest) returning no items? + + + This most commonly happens when the request has already been parsed, or + processed in some other way. Since the input stream has aleady been + consumed by that earlier process, it is no longer available for parsing + by Commons FileUpload. + + + + + + Why am I getting "Read timed out" exceptions while parsing? + + + The most common cause of these exceptions is when FileUpload is being + used on a site that is using the Tomcat ISAPI redirector. There was a + bug in earlier versions of that component that caused problems with + multipart requests. The bug was fixed some time ago, so you probably + just need to pick up a newer version. See the + Tomcat bug report + for full details. + + + + + + Why is NoClassDefFoundError being thrown? + + +

There are two common causes for this error.

+ +

Firstly, it might simply mean that you do not have the Commons IO + jar in your classpath. DiskFileUpload depends on IO (see + dependencies) - you can tell if + this is the case if the missing class is within the + org.apache.commons.io package.

+ +

Secondly this can happen when attempting to rely on a shared copy of + the Commons FileUpload jar file provided by your web container. The + solution is to include the FileUpload jar file as part of your own + web application, instead of relying on the container. The same may + hold for FileUpload's IO dependency.

+
+
+ + + + Why does FileItem.getFileName() return the whole path, + and not just the file name? + + + Internet Explorer provides the entire path to the uploaded file and not + just the base file name. Since FileUpload provides exactly what was + supplied by the client (browser), you may want to remove this path + information in your application. You can do that using the following + method from Commons IO (which you may already have, since it is used by + DiskFileUpload). +
+    String fileName = item.getName();
+    if (fileName != null) {
+        filename = FilenameUtils.getName(filename);
+    }
+        
+
+
+
+ + + FileUpload and Struts + + + + I'm using FileUpload in an Action, but it's not working. Why? + + + Struts recognises multipart requests, and parses them automatically, + presenting the request parameters to your code in the same manner as + if they were regular request parameters. Since Struts has already + processed the request, and made it available in your form bean, the + input stream is no longer available for parsing, so attempting to do + so with FileUpload will fail. + + + + + + But I need to parse the request myself. How can I do that? + + + Struts parses multipart a request as a part of the process of populating + your form bean from that request. If, for some reason, you need to have + full control over the multipart parsing, you can do so by configuring + your action mapping without an associated form bean. (A better way of + doing this, however, is to replace the default multipart handler with + your own. See the Struts documentation for details.) + + + + +
Modified: commons/sandbox/commons-fileupload2/src/site/site.xml URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/site.xml?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/site/site.xml (original) +++ commons/sandbox/commons-fileupload2/src/site/site.xml Mon Jun 21 08:29:22 2010 @@ -15,27 +15,26 @@ See the License for the specific language governing permissions and limitations under the License. --> - + - Commons FileUpload + Commons FileUpload 2 /images/logo.png /index.html - - - - - + + + + + - - - - - + + + + Modified: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java?rev=956490&r1=956489&r2=956490&view=diff ============================================================================== --- commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java (original) +++ commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java Mon Jun 21 08:29:22 2010 @@ -33,7 +33,6 @@ import java.util.Arrays; import org.apache.commons.fileupload2.disk.DiskFileItem; import org.apache.commons.fileupload2.disk.DiskFileItemStore; import org.apache.commons.fileupload2.impl.AbstractFileItem; -import org.apache.commons.fileupload2.impl.MemoryFileItem; import org.apache.commons.fileupload2.util.Streams; import org.junit.Test; @@ -116,7 +115,7 @@ public class DefaultFileItemTest { final FileItemStore fileItemStore = createFileItemStore(null); final StoredFileItem storedFileItem = fileItemStore.store(item); assertNotNull(storedFileItem); - assertTrue(storedFileItem instanceof MemoryFileItem); + assertTrue(storedFileItem.isInMemory()); assertEquals(testFieldValueBytes.length, storedFileItem.getContentLength()); assertTrue(Arrays.equals(Streams.asByteArray(storedFileItem.getInputStream()), testFieldValueBytes)); assertEquals(Streams.asString(storedFileItem.getInputStream()), textFieldValue); @@ -136,8 +135,15 @@ public class DefaultFileItemTest { */ @Test public void testAboveThresholdSpecifiedRepository() throws IOException { String tempPath = System.getProperty("java.io.tmpdir"); - String tempDirName = "testAboveThresholdSpecifiedRepository"; - File tempDir = new File(tempPath, tempDirName); + String tempDirName; + File tempDir; + for (int i = 0; ; i++) { + tempDirName = "testAboveThresholdSpecifiedRepository" + (i == 0 ? "" : String.valueOf(i)); + tempDir = new File(tempPath, tempDirName); + if (!tempDir.exists()) { + break; + } + } tempDir.mkdir(); doTestAboveThreshold(tempDir); assertTrue(tempDir.delete()); @@ -161,7 +167,7 @@ public class DefaultFileItemTest { assertNotNull(item); FileItemStore factory = createFileItemStore(repository); final StoredFileItem storedFileItem = factory.store(item); - assertTrue(storedFileItem instanceof DiskFileItem); + assertTrue(!storedFileItem.isInMemory()); assertEquals(testFieldValueBytes.length, storedFileItem.getContentLength()); assertTrue(Arrays.equals(Streams.asByteArray(storedFileItem.getInputStream()), testFieldValueBytes)); assertEquals(Streams.asString(storedFileItem.getInputStream()), textFieldValue);