📄 multipartrequest.java
字号:
/*
*
* Copyright (c) 2004 SourceTap - www.sourcetap.com
*
* The contents of this file are subject to the SourceTap Public License
* ("License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.sourcetap.com/license.htm
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
*/
package http.utils.multipartrequest;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
A Multipart form data parser. Parses an input stream and writes out any files found,
making available a hashtable of other url parameters. As of version 1.17 the files can
be saved to memory, and optionally written to a database, etc.
<BR>
<BR>
Copyright (C)2001 Jason Pell.
<BR>
<PRE>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
<BR>
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
<BR>
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<BR>
Email: jasonpell@hotmail.com
Url: http://www.geocities.com/jasonpell
</PRE>
@author Jason Pell
@version 1.20 A very minor fix, but one apparently that was causing some serious issues for some users. The intTotalRead
integer was being set to -1, which meant that it was always off by one when comparing to Content-Length.
Thanks to David Tuma for this fix. 19/10/2001
@version 1.19 Moved the MultipartRequest into a package, and thus into a java archive for easier dissemination.
Fixed a bug, where in netscape if a file was uploaded with an unrecognised extension, no Content-Type
was specified, so the first line of the file was chopped off. Also modified the structure of the parse
method to make it easier to manage. I was checking strFileName length and nullness in two if blocks,
so I moved them together. This should make the parse(...) method easier to understand as well. 26/07/2001
@version 1.18 Fixed some serious bugs. A new method readAndWrite(InputStream in, OutputStream out) which now does
the generic processing in common for readAndWriteFile and readFile. The differences are that now
the two extra bytes at the end of a file upload are processed once, instead of after each line. Also
if an empty file is encountered, an outputstream is opened, but then deleted if no data written to it.
The getCharArray() method has been removed. Replaced by the new String(bytes, encoding) method using
ISO8859_1 encoding to ensure that extended characters are supported. All creation of strings is done
using this encoding. The addition of static methods setEncoding(String) and getEncoding() to allow the
use of MultipartRequest with a specific encoding type. All instances of MultipartRequest will utilise
the static charEncoding variable value, that the setEncoding() method can be used to set.
Hopefully this will not introduce any latent problems. Started to introduce support for multiple file
uploads with the same form field name, but not completed for v1.18. 26/06/2001
@version 1.17 A few _very_ minor fixes. Plus a cool new feature added. The ability to save files into memory.
<b>Thanks to Mark Latham for the idea and some of the code.</b> 11/04/2001
@version 1.16 Added support for multiple parameter values. Also fixed getCharArray(...) method to support
parameters with non-english ascii values (ascii above 127). Thanks to Stefan Schmidt &
Michael Elvers for this. (No fix yet for reported problems with Tomcat 3.2 or a single extra
byte appended to uploads of certain files). By 1.17 hopefully will have a resolution for the
second problem. 14/03/2001
@version 1.15 A new parameter added, intMaxReadBytes, to allow arbitrary length files. Released under
the LGPL (Lesser General Public License). 03/02/2001
@version 1.14 Fix for IE problem with filename being empty. This is because IE includes a default Content-Type
even when no file is uploaded. 16/02/2001
@version 1.13 If an upload directory is not specified, then all file contents are sent into oblivion, but the
rest of the parsing works as normal.
@version 1.12 Fix, was allowing zero length files. Will not even create the output file until there is
something to write. getFile(String) now returns null, if a zero length file was specified. 06/11/2000
@version 1.11 Fix, in case Content-type is not specified.
@version 1.1 Removed dependence on Servlets. Now passes in a generic InputStream instead.
"Borrowed" readLine from Tomcat 3.1 ServletInputStream class,
so we can remove some of the dependencies on ServletInputStream.
Fixed bug where a empty INPUT TYPE="FILE" value, would cause an exception.
@version 1.0 Initial Release.
*/
public class MultipartRequest {
/**
Define Character Encoding method here.
*/
private static String charEncoding = "ISO-8859-1";
/**
Prevent a denial of service by defining this, will never read more data.
If Content-Length is specified to be more than this, will throw an exception.
This limits the maximum number of bytes to the value of an int, which is 2 Gigabytes.
*/
public static final int MAX_READ_BYTES = 100 * (1024 * 1024); // 100MB!
/**
Defines the number of bytes to read per readLine call. 128K
*/
public static final int READ_LINE_BLOCK = 1024 * 128;
/**
Define the array indexes for the htFiles Object array.
*/
public static final int FILENAME = 0;
public static final int CONTENT_TYPE = 1;
public static final int SIZE = 2;
// Only used for file upload to memory.
public static final int CONTENTS = 3;
// If not null, send debugging out here.
private PrintWriter debug = null;
private Hashtable htParameters = null;
private Hashtable htFiles = null;
private String strBoundary = null;
// If this Directory spec remains null, writing of files will be disabled...
private File fileOutPutDirectory = null;
// prefix to put on front of file name, to insure files are unique
private String filePrefix = null;
private boolean loadIntoMemory = false;
private long intContentLength;
private long intTotalRead;
/**
Store a read from the input stream here. Global so we do not keep creating new arrays each read.
*/
private byte[] blockOfBytes = null;
/**
* Constructor.
*
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</b>
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(String strContentTypeText, int intContentLength,
InputStream in, String strSaveDirectory)
throws IllegalArgumentException, IOException {
this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
null, MAX_READ_BYTES);
}
/**
* Constructor.
*
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</b>
* @param strFilePrefix Prepend this prefix onto the filename. can be used to insure unique file names
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(String strContentTypeText, int intContentLength,
InputStream in, String strSaveDirectory, String strFilePrefix)
throws IllegalArgumentException, IOException {
this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
strFilePrefix, MAX_READ_BYTES);
}
/**
* Constructor.
*
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</B>
* @param intMaxReadBytes Overrides the MAX_BYTES_READ value, to allow arbitrarily long files.
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(String strContentTypeText, int intContentLength,
InputStream in, String strSaveDirectory, int intMaxReadBytes)
throws IllegalArgumentException, IOException {
this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
null, intMaxReadBytes);
}
/**
* Constructor.
*
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</B>
* @param strFilePrefix Prepend this prefix onto the filename. can be used to insure unique file names
* @param intMaxReadBytes Overrides the MAX_BYTES_READ value, to allow arbitrarily long files.
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(String strContentTypeText, int intContentLength,
InputStream in, String strSaveDirectory, String strFilePrefix,
int intMaxReadBytes) throws IllegalArgumentException, IOException {
this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
strFilePrefix, intMaxReadBytes);
}
/**
* Constructor.
*
* @param debug A PrintWriter that can be used for debugging.
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</B>
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
* @deprecated Replaced by MultipartRequest(PrintWriter, String, int, InputStream, int)
* You can specify MultipartRequest.MAX_READ_BYTES for the intMaxReadBytes parameter
*/
public MultipartRequest(PrintWriter debug, String strContentTypeText,
int intContentLength, InputStream in, String strSaveDirectory)
throws IllegalArgumentException, IOException {
this(debug, strContentTypeText, intContentLength, in, strSaveDirectory,
null, MAX_READ_BYTES);
}
/**
* Constructor - load into memory constructor
*
* @param debug A PrintWriter that can be used for debugging.
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param intMaxReadBytes Overrides the MAX_BYTES_READ value, to allow arbitrarily long files.
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(PrintWriter debug, String strContentTypeText,
int intContentLength, InputStream in, int intMaxReadBytes)
throws IllegalArgumentException, IOException {
this.loadIntoMemory = true;
// Now initialise the object, which will actually call the parse method to parse multipart stream.
init(debug, strContentTypeText, intContentLength, in, intMaxReadBytes);
}
/**
* Constructor.
*
* @param debug A PrintWriter that can be used for debugging.
* @param strContentTypeText The "Content-Type" HTTP header value.
* @param intContentLength The "Content-Length" HTTP header value.
* @param in The InputStream to read and parse.
* @param strSaveDirectory The temporary directory to save the file from where they can then be moved to wherever by the
* calling process. <b>If you specify <u>null</u> for this parameter, then any files uploaded
* will be silently ignored.</B>
* @param intMaxReadBytes Overrides the MAX_BYTES_READ value, to allow arbitrarily long files.
*
* @exception IllegalArgumentException If the strContentTypeText does not contain a Content-Type of "multipart/form-data" or the boundary is not found.
* @exception IOException If the intContentLength is higher than MAX_READ_BYTES or strSaveDirectory is invalid or cannot be written to.
*
* @see #MAX_READ_BYTES
*/
public MultipartRequest(PrintWriter debug, String strContentTypeText,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -