?? multipartrequest.java
字號:
// Copyright (C) 1998 by Jason Hunter <jhunter@acm.org>. All rights reserved.// Use of this class is limited. Please see the LICENSE for more information.package fengyun.Fastmail.util;import java.io.*;import java.util.*;import javax.servlet.*;/** * A utility class to handle <tt>multipart/form-data</tt> requests, * the kind of requests that support file uploads. This class can * receive arbitrarily large files (up to an artificial limit you can set), * and fairly efficiently too. * It cannot handle nested data (multipart content within multipart content) * or internationalized content (such as non Latin-1 filenames). * <p> * It's used like this: * <blockquote><pre> * MultipartRequest multi = new MultipartRequest(req, "."); * * out.println("Params:"); * Enumeration params = multi.getParameterNames(); * while (params.hasMoreElements()) { * String name = (String)params.nextElement(); * String value = multi.getParameter(name); * out.println(name + " = " + value); * } * out.println(); * * out.println("Files:"); * Enumeration files = multi.getFileNames(); * while (files.hasMoreElements()) { * String name = (String)files.nextElement(); * String filename = multi.getFilesystemName(name); * String type = multi.getContentType(name); * File f = multi.getFile(name); * out.println("name: " + name); * out.println("filename: " + filename); * out.println("type: " + type); * if (f != null) { * out.println("f.toString(): " + f.toString()); * out.println("f.getName(): " + f.getName()); * out.println("f.exists(): " + f.exists()); * out.println("f.length(): " + f.length()); * out.println(); * } * } * </pre></blockquote> * * A client can upload files using an HTML form with the following structure. * Note that not all browsers support file uploads. * <blockquote><pre> * <FORM ACTION="/servlet/Handler" METHOD=POST * ENCTYPE="multipart/form-data"> * What is your name? <INPUT TYPE=TEXT NAME=submitter> <BR> * Which file to upload? <INPUT TYPE=FILE NAME=file> <BR> * <INPUT TYPE=SUBMIT> * </FORM> * </pre></blockquote> * <p> * The full file upload specification is contained in experimental RFC 1867, * available at <a href="http://ds.internic.net/rfc/rfc1867.txt"> * http://ds.internic.net/rfc/rfc1867.txt</a>. * * @author <b>Jason Hunter</b>, Copyright © 1998-1999 * @version 1.2, 99/12/20, IE4 on Mac readNextPart() bug fix * @version 1.1, 99/01/15, JSDK readLine() bug workaround * @version 1.0, 98/09/18 */public class MultipartRequest { private static final int DEFAULT_MAX_POST_SIZE = 1024 * 1024; // 1 Meg private ServletRequest req; private File dir; private int maxSize; private Hashtable parameters = new Hashtable(); // name - value private Hashtable files = new Hashtable(); // name - UploadedFile /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to 1 Megabyte. If the content is too large, an * IOException is thrown. This constructor actually parses the * <tt>multipart/form-data</tt> and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request * @param saveDirectory the directory in which to save any uploaded files * @exception IOException if the uploaded content is larger than 1 Megabyte * or there's a problem reading or parsing the request */ public MultipartRequest(ServletRequest request, String saveDirectory) throws IOException { this(request, saveDirectory, DEFAULT_MAX_POST_SIZE); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * <tt>multipart/form-data</tt> and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request * @param saveDirectory the directory in which to save any uploaded files * @param maxPostSize the maximum size of the POST content * @exception IOException if the uploaded content is larger than * <tt>maxPostSize</tt> or there's a problem reading or parsing the request */ public MultipartRequest(ServletRequest request, String saveDirectory, int maxPostSize) throws IOException { // Sanity check values if (request == null) throw new IllegalArgumentException("request cannot be null"); if (saveDirectory == null) throw new IllegalArgumentException("saveDirectory cannot be null"); if (maxPostSize <= 0) { throw new IllegalArgumentException("maxPostSize must be positive"); } // Save the request, dir, and max size req = request; dir = new File(saveDirectory); maxSize = maxPostSize; // Check saveDirectory is truly a directory if (!dir.isDirectory()) throw new IllegalArgumentException("Not a directory: " + saveDirectory); // Check saveDirectory is writable if (!dir.canWrite()) throw new IllegalArgumentException("Not writable: " + saveDirectory); // Now parse the request saving data to "parameters" and "files"; // write the file contents to the saveDirectory readRequest(); } /** * Returns the names of all the parameters as an Enumeration of * Strings. It returns an empty Enumeration if there are no parameters. * * @return the names of all the parameters as an Enumeration of Strings */ public Enumeration getParameterNames() { return parameters.keys(); } /** * Returns the names of all the uploaded files as an Enumeration of * Strings. It returns an empty Enumeration if there are no uploaded * files. Each file name is the name specified by the form, not by * the user. * * @return the names of all the uploaded files as an Enumeration of Strings */ public Enumeration getFileNames() { return files.keys(); } /** * Returns the value of the named parameter as a String, or null if * the parameter was not given. The value is guaranteed to be in its * normal, decoded form. If the parameter has multiple values, only * the last one is returned. * * @param name the parameter name * @return the parameter value */ public String getParameter(String name) { try { String param = (String)parameters.get(name); if (param.equals("")) return null; return param; } catch (Exception e) { return null; } } /** * Returns the filesystem name of the specified file, or null if the * file was not included in the upload. A filesystem name is the name * specified by the user. It is also the name under which the file is * actually saved. * * @param name the file name * @return the filesystem name of the file */ public String getFilesystemName(String name) { try { UploadedFile file = (UploadedFile)files.get(name); return file.getFilesystemName(); // may be null } catch (Exception e) { return null; } } /** * Returns the content type of the specified file (as supplied by the * client browser), or null if the file was not included in the upload. * * @param name the file name * @return the content type of the file */ public String getContentType(String name) { try { UploadedFile file = (UploadedFile)files.get(name); return file.getContentType(); // may be null } catch (Exception e) { return null; } } /** * Returns a File object for the specified file saved on the server's * filesystem, or null if the file was not included in the upload. * * @param name the file name * @return a File object for the named file */ public File getFile(String name) { try { UploadedFile file = (UploadedFile)files.get(name); return file.getFile(); // may be null } catch (Exception e) { return null; } } /** * The workhorse method that actually parses the request. A subclass * can override this method for a better optimized or differently * behaved implementation. * * @exception IOException if the uploaded content is larger than * <tt>maxSize</tt> or there's a problem parsing the request */ protected void readRequest() throws IOException { // Check the content type to make sure it's "multipart/form-data" String type = req.getContentType(); if (type == null || !type.toLowerCase().startsWith("multipart/form-data")) { throw new IOException("Posted content type isn't multipart/form-data"); } // Check the content length to prevent denial of service attacks int length = req.getContentLength(); if (length > maxSize) { throw new IOException("Posted content length of " + length + " exceeds limit of " + maxSize); } // Get the boundary string; it's included in the content type. // Should look something like "------------------------12012133613061" String boundary = extractBoundary(type); if (boundary == null) { throw new IOException("Separation boundary was not specified"); } // Construct the special input stream we'll read from MultipartInputStreamHandler in = new MultipartInputStreamHandler(req.getInputStream(), length); // Read the first line, should be the first boundary String line = in.readLine(); if (line == null) { throw new IOException("Corrupt form data: premature ending"); } // Verify that the line is the boundary if (!line.startsWith(boundary)) { throw new IOException("Corrupt form data: no leading boundary"); } // Now that we're just beyond the first boundary, loop over each part boolean done = false; while (!done) { done = readNextPart(in, boundary); } } /** * A utility method that reads an individual part. Dispatches to * readParameter() and readAndSaveFile() to do the actual work. A * subclass can override this method for a better optimized or * differently behaved implementation. * * @param in the stream from which to read the part * @param boundary the boundary separating parts * @return a flag indicating whether this is the last part * @exception IOException if there's a problem reading or parsing the * request * * @see readParameter * @see readAndSaveFile */ protected boolean readNextPart(MultipartInputStreamHandler in, String boundary) throws IOException { // Read the first line, should look like this: // content-disposition: form-data; name="field1"; filename="file1.txt" String line = in.readLine(); if (line == null) { // No parts left, we're done return true; } else if (line.length() == 0) { // IE4 on Mac sends an empty line at the end; treat that as the end // Thanks to Daniel Lemire and Henri Tourigny for this bug fix return true; } // Parse the content-disposition line String[] dispInfo = extractDispositionInfo(line); String disposition = dispInfo[0];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -