|
What this is
Other links
The source code/* * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/fileupload/FileUpload.java,v 1.4 2004/10/15 09:41:20 minhnn Exp $ * $Revision: 1.4 $ * $Date: 2004/10/15 09:41:20 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package net.myvietnam.mvncore.fileupload; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.Map; import java.util.List; import java.util.ArrayList; import java.util.HashMap; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.MethodUtils; /** * <p>High level API for processing file uploads. * * <p>This class handles multiple files per single HTML widget, sent using * <code>multipar/mixed encoding type, as specified by * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867. Use {@link * #parseRequest(HttpServletRequest)} to acquire a list of {@link * net.myvietnam.mvncore.fileupload.FileItem}s associated with a given HTML * widget. * * <p> Files will be stored in temporary disk storage or in memory, * depending on request size, and will be available as {@link * net.myvietnam.mvncore.fileupload.FileItem}s. * * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski * @author <a href="mailto:dlr@collab.net">Daniel Rall * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl * @author <a href="mailto:jmcnally@collab.net">John McNally * @author <a href="mailto:martinc@apache.org">Martin Cooper * * @version $Id: FileUpload.java,v 1.4 2004/10/15 09:41:20 minhnn Exp $ */ public class FileUpload { // ----------------------------------------------------- Manifest constants /** * HTTP content type header name. */ public static final String CONTENT_TYPE = "Content-type"; /** * HTTP content disposition header name. */ public static final String CONTENT_DISPOSITION = "Content-disposition"; /** * Content-disposition value for form data. */ public static final String FORM_DATA = "form-data"; /** * Content-disposition value for file attachment. */ public static final String ATTACHMENT = "attachment"; /** * Part of HTTP content type header. */ private static final String MULTIPART = "multipart/"; /** * HTTP content type header for multipart forms. */ public static final String MULTIPART_FORM_DATA = "multipart/form-data"; /** * HTTP content type header for multiple uploads. */ public static final String MULTIPART_MIXED = "multipart/mixed"; /** * The maximum length of a single header line that will be parsed * (1024 bytes). */ public static final int MAX_HEADER_SIZE = 1024; // ----------------------------------------------------------- Data members /** * The maximum size permitted for an uploaded file. */ private int sizeMax; /** * The threshold above which uploads will be stored on disk. */ private int sizeThreshold; /** * The path to which uploaded files will be stored, if stored on disk. */ private String repositoryPath; /** * The name of the class to use for <code>FileItems. */ private String fileItemClassName = "net.myvietnam.mvncore.fileupload.DefaultFileItem"; /** * The cached method for obtaining a new <code>FileItem instance. */ private Method newInstanceMethod; // ----------------------------------------------------- Property accessors /** * Returns the maximum allowed upload size. * * @return The maximum allowed size, in bytes. */ public int getSizeMax() { return sizeMax; } /** * Sets the maximum allowed upload size. If negative, there is no maximum. * * @param sizeMax The maximum allowed size, in bytes, or -1 for no maximum. */ public void setSizeMax(int sizeMax) { this.sizeMax = sizeMax; } /** * Returns the size threshold beyond which files are written directly to * disk. The default value is 1024 bytes. * * @return The size threshold, in bytes. */ public int getSizeThreshold() { return sizeThreshold; } /** * Sets the size threshold beyond which files are written directly to disk. * * @param sizeThreshold The size threshold, in bytes. */ public void setSizeThreshold(int sizeThreshold) { this.sizeThreshold = sizeThreshold; } /** * Returns the location used to temporarily store files that are larger * than the configured size threshold. * * @return The path to the temporary file location. */ public String getRepositoryPath() { return repositoryPath; } /** * Sets the location used to temporarily store files that are larger * than the configured size threshold. * * @param repositoryPath The path to the temporary file location. */ public void setRepositoryPath(String repositoryPath) { this.repositoryPath = repositoryPath; } /** * Returns the fully qualified name of the class which will be used to * instantiate <code>FileItem instances when a request is parsed. * * @return The fully qualified name of the Java class. */ public String getFileItemClassName() { return fileItemClassName; } /** * Sets the fully qualified name of the class which will be used to * instantiate <code>FileItem instances when a request is parsed. * * @param fileItemClassName The fully qualified name of the Java class. */ public void setFileItemClassName(String fileItemClassName) { this.fileItemClassName = fileItemClassName; this.newInstanceMethod = null; } // --------------------------------------------------------- Public methods /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867 * compliant <code>multipart/form-data stream. If files are stored * on disk, the path is given by <code>getRepositoryPath(). * * @param req The servlet request to be parsed. * * @return A list of <code>FileItem instances parsed from the * request, in the order that they were transmitted. * * @exception FileUploadException if there are problems reading/parsing * the request or storing files. */ public List /* FileItem */ parseRequest(HttpServletRequest req) throws FileUploadException { return parseRequest(req, getSizeThreshold(), getSizeMax(), getRepositoryPath()); } /** * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867 * compliant <code>multipart/form-data stream. If files are stored * on disk, the path is given by <code>getRepositoryPath(). * * @param req The servlet request to be parsed. * @param sizeThreshold The max size in bytes to be stored in memory. * @param sizeMax The maximum allowed upload size, in bytes. * @param path The location where the files should be stored. * * @return A list of <code>FileItem instances parsed from the * request, in the order that they were transmitted. * * @exception FileUploadException if there are problems reading/parsing * the request or storing files. */ public List /* FileItem */ parseRequest(HttpServletRequest req, int sizeThreshold, int sizeMax, String path) throws FileUploadException { ArrayList items = new ArrayList(); String contentType = req.getHeader(CONTENT_TYPE); if (!contentType.startsWith(MULTIPART)) { throw new FileUploadException("the request doesn't contain a " + MULTIPART_FORM_DATA + " or " + MULTIPART_MIXED + " stream"); } int requestSize = req.getContentLength(); if (requestSize == -1) { throw new FileUploadException("the request was rejected because " + "it's size is unknown"); } if (sizeMax >= 0 && requestSize > sizeMax) { throw new FileUploadException("the request was rejected because " + "it's size exceeds allowed range (request size = " + requestSize + " but max size = " + sizeMax + ")"); } try { byte[] boundary = contentType.substring( contentType.indexOf("boundary=") + 9).getBytes(); InputStream input = req.getInputStream(); MultipartStream multi = new MultipartStream(input, boundary); boolean nextPart = multi.skipPreamble(); while (nextPart) { Map headers = parseHeaders(multi.readHeaders()); String fieldName = getFieldName(headers); if (fieldName != null) { String subContentType = getHeader(headers, CONTENT_TYPE); if (subContentType != null && subContentType .startsWith(MULTIPART_MIXED)) { // Multiple files. byte[] subBoundary = subContentType.substring( subContentType .indexOf("boundary=") + 9).getBytes(); multi.setBoundary(subBoundary); boolean nextSubPart = multi.skipPreamble(); while (nextSubPart) { headers = parseHeaders(multi.readHeaders()); if (getFileName(headers) != null) { FileItem item = createItem(sizeThreshold, path, headers, requestSize); OutputStream os = ((DefaultFileItem) item).getOutputStream(); try { multi.readBodyData(os); } finally { os.close(); } item.setFieldName(getFieldName(headers)); items.add(item); } else { // Ignore anything but files inside // multipart/mixed. multi.discardBodyData(); } nextSubPart = multi.readBoundary(); } multi.setBoundary(boundary); } else { if (getFileName(headers) != null) { // A single file. FileItem item = createItem(sizeThreshold, path, headers, requestSize); OutputStream os = ((DefaultFileItem) item).getOutputStream(); try { multi.readBodyData(os); } finally { os.close(); } item.setFieldName(getFieldName(headers)); items.add(item); } else { // A form field. FileItem item = createItem(sizeThreshold, path, headers, requestSize); OutputStream os = ((DefaultFileItem) item).getOutputStream(); try { multi.readBodyData(os); } finally { os.close(); } item.setFieldName(getFieldName(headers)); item.setIsFormField(true); items.add(item); } } } else { // Skip this part. multi.discardBodyData(); } nextPart = multi.readBoundary(); } } catch (IOException e) { throw new FileUploadException( "Processing of " + MULTIPART_FORM_DATA + " request failed. " + e.getMessage()); } return items; } // ------------------------------------------------------ Protected methods /** * Retrieves the file name from the <code>Content-disposition * header. * * @param headers A <code>Map containing the HTTP request headers. * * @return The file name for the current <code>encapsulation. */ protected String getFileName(Map /* String, String */ headers) { String fileName = null; String cd = getHeader(headers, CONTENT_DISPOSITION); if (cd.startsWith(FORM_DATA) || cd.startsWith(ATTACHMENT)) { int start = cd.indexOf("filename=\""); int end = cd.indexOf('"', start + 10); if (start != -1 && end != -1) { fileName = cd.substring(start + 10, end).trim(); } } return fileName; } /** * Retrieves the field name from the <code>Content-disposition * header. * * @param headers A <code>Map containing the HTTP request headers. * * @return The field name for the current <code>encapsulation. */ protected String getFieldName(Map /* String, String */ headers) { String fieldName = null; String cd = getHeader(headers, CONTENT_DISPOSITION); if (cd != null && cd.startsWith(FORM_DATA)) { int start = cd.indexOf("name=\""); int end = cd.indexOf('"', start + 6); if (start != -1 && end != -1) { fieldName = cd.substring(start + 6, end); } } return fieldName; } /** * Creates a new {@link net.myvietnam.mvncore.fileupload.FileItem} instance. * * @param sizeThreshold The max size in bytes to be stored in memory. * @param path The path for the FileItem. * @param headers A <code>Map containing the HTTP request * headers. * @param requestSize The total size of the request, in bytes. * * @return A newly created <code>FileItem instance. * * @exception FileUploadException if an error occurs. */ protected FileItem createItem(int sizeThreshold, String path, Map /* String, String */ headers, int requestSize) throws FileUploadException { Method newInstanceMethod = getNewInstanceMethod(); Object[] args = new Object[] { path, getFileName(headers), getHeader(headers, CONTENT_TYPE), new Integer(requestSize), new Integer(sizeThreshold) }; FileItem fileItem = null; try { fileItem = (FileItem) newInstanceMethod.invoke(null, args); } catch (Exception e) { throw new FileUploadException(e.toString()); } return fileItem; } /** * <p> Returns the |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.