You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ms...@apache.org on 2001/04/12 00:56:31 UTC
cvs commit: jakarta-struts/web/upload display.jsp upload.jsp
mschachter 01/04/11 15:56:30
Modified: src/share/org/apache/struts/upload
DiskMultipartRequestHandler.java
MultipartIterator.java
src/upload/org/apache/struts/webapp/upload UploadAction.java
UploadForm.java
web/upload display.jsp upload.jsp
Added: src/share/org/apache/struts/upload
BufferedMultipartInputStream.java
Log:
- Added file BufferedMultipartInputStream to
handle buffering for ServletInputStream
on it's own, and to provide a safer readLine() method
- Added support for indexed values in multipart forms
An interesting side to this, the time it takes for a file to upload
seems to be dependant on the browser being used to upload. For example
there is a big difference between using Internet Explorer 5.5 and Opera 3.6, with
Opera being about 7-10 times faster.
Revision Changes Path
1.8 +221 -208 jakarta-struts/src/share/org/apache/struts/upload/DiskMultipartRequestHandler.java
Index: DiskMultipartRequestHandler.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/upload/DiskMultipartRequestHandler.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- DiskMultipartRequestHandler.java 2001/02/14 21:43:05 1.7
+++ DiskMultipartRequestHandler.java 2001/04/11 22:56:19 1.8
@@ -1,209 +1,222 @@
-package org.apache.struts.upload;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.FileOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Hashtable;
-import java.util.Enumeration;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.struts.action.ActionServlet;
-import org.apache.struts.action.ActionMapping;
-
-/**
- * This is a MultipartRequestHandler that writes file data directly to
- * to temporary files on disk
- *
- * @author Mike Schachter
- */
-public class DiskMultipartRequestHandler implements MultipartRequestHandler {
-
- /**
- * The ActionServlet instance used for this class
- */
- protected ActionServlet servlet;
-
- /**
- * The ActionMapping instance used for this class
- */
- protected ActionMapping mapping;
-
- /**
- * A Hashtable representing the form files uploaded
- */
- protected Hashtable fileElements;
-
- /**
- * A Hashtable representing the form text input names and values
- */
- protected Hashtable textElements;
-
- /**
- * A Hashtable representing all elemnents
- */
- protected Hashtable allElements;
-
- /**
- * The temporary directory
- */
- protected String tempDir;
-
- public void handleRequest(HttpServletRequest request) throws ServletException {
-
- retrieveTempDir();
-
- MultipartIterator iterator = new MultipartIterator(request,
- servlet.getBufferSize(),
- getMaxSizeFromServlet(),
- tempDir);
- MultipartElement element;
-
- textElements = new Hashtable();
- fileElements = new Hashtable();
- allElements = new Hashtable();
-
- try {
- while ((element = iterator.getNextElement()) != null) {
- if (!element.isFile()) {
- textElements.put(element.getName(), element.getValue());
- allElements.put(element.getName(), element.getValue());
- }
- else {
-
- File tempFile = element.getFile();
- if (tempFile.exists()) {
- DiskFile theFile = new DiskFile(tempFile.getAbsolutePath());
- theFile.setContentType(element.getContentType());
- theFile.setFileName(element.getFileName());
- theFile.setFileSize((int) tempFile.length());
- fileElements.put(element.getName(), theFile);
- allElements.put(element.getName(), theFile);
- }
- }
- }
- }
- catch (UnsupportedEncodingException uee) {
- throw new ServletException("Encoding \"ISO-8859-1\" not supported");
- }
-
- }
-
- public Hashtable getAllElements() {
- return allElements;
- }
-
- public Hashtable getTextElements() {
- return textElements;
- }
-
- public Hashtable getFileElements() {
- return fileElements;
- }
-
- /**
- * Delete all the files uploaded
- */
- public void rollback() {
- Enumeration names = fileElements.keys();
-
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- DiskFile theFile = (DiskFile) fileElements.get(name);
- theFile.destroy();
- }
- }
-
- /**
- * Calls on {@link #rollback() rollback()} to delete
- * temporary files
- */
- public void finish() {
- rollback();
- }
-
- public void setServlet(ActionServlet servlet) {
- this.servlet = servlet;
- }
-
- public void setMapping(ActionMapping mapping) {
- this.mapping = mapping;
- }
-
- public ActionServlet getServlet() {
- return servlet;
- }
-
- public ActionMapping getMapping() {
- return mapping;
- }
-
- /**
- * Gets the maximum post data size in bytes from the string
- * representation in ActionServlet
- */
- protected long getMaxSizeFromServlet() throws ServletException{
- String stringSize = servlet.getMaxFileSize();
- long size = -1;
- int multiplier = 1;
-
- if (stringSize.endsWith("K")) {
- multiplier = 1024;
- stringSize = stringSize.substring(0, stringSize.length()-1);
- }
- if (stringSize.endsWith("M")) {
- multiplier = 1024*1024;
- stringSize = stringSize.substring(0, stringSize.length()-1);
- }
- else if (stringSize.endsWith("G")) {
- multiplier = 1024*1024*1024;
- stringSize = stringSize.substring(0, stringSize.length()-1);
- }
-
- try {
- size = Long.parseLong(stringSize);
- }
- catch (NumberFormatException nfe) {
- throw new ServletException("Invalid format for maximum file size: \"" +
- servlet.getMaxFileSize() + "\"");
- }
-
- return (size * multiplier);
- }
-
- /**
- * Retrieves the temporary directory from either ActionServlet, a context
- * property, or a system property, in that order
- */
- protected void retrieveTempDir() {
- //get a handle to some temporary file and open
- //a stream to it
- tempDir = servlet.getTempDir();
- if (tempDir == null) {
- //attempt to retrieve the servlet container's temporary directory
- ServletContext context = servlet.getServletConfig().getServletContext();
-
- try {
- tempDir = (String) context.getAttribute("javax.servlet.context.tempdir");
- }
- catch (ClassCastException cce) {
- tempDir = ((File) context.getAttribute("javax.servlet.context.tempdir")).getAbsolutePath();
- }
-
-
- if (tempDir == null) {
- //default to system-wide tempdir
- tempDir = System.getProperty("java.io.tmpdir");
-
- if (servlet.getDebug() > 1) {
- servlet.log("DiskMultipartRequestHandler.handleRequest(): " +
- "defaulting to java.io.tmpdir directory \"" +
- tempDir);
- }
- }
- }
- }
+package org.apache.struts.upload;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.ActionMapping;
+
+/**
+ * This is a MultipartRequestHandler that writes file data directly to
+ * to temporary files on disk
+ *
+ * @author Mike Schachter
+ */
+public class DiskMultipartRequestHandler implements MultipartRequestHandler {
+
+ /**
+ * The ActionServlet instance used for this class
+ */
+ protected ActionServlet servlet;
+
+ /**
+ * The ActionMapping instance used for this class
+ */
+ protected ActionMapping mapping;
+
+ /**
+ * A Hashtable representing the form files uploaded
+ */
+ protected Hashtable fileElements;
+
+ /**
+ * A Hashtable representing the form text input names and values
+ */
+ protected Hashtable textElements;
+
+ /**
+ * A Hashtable representing all elemnents
+ */
+ protected Hashtable allElements;
+
+ /**
+ * The temporary directory
+ */
+ protected String tempDir;
+
+ public void handleRequest(HttpServletRequest request) throws ServletException {
+
+ retrieveTempDir();
+
+ MultipartIterator iterator = new MultipartIterator(request,
+ servlet.getBufferSize(),
+ getMaxSizeFromServlet(),
+ tempDir);
+ MultipartElement element;
+
+ textElements = new Hashtable();
+ fileElements = new Hashtable();
+ allElements = new Hashtable();
+
+ try {
+ while ((element = iterator.getNextElement()) != null) {
+ if (!element.isFile()) {
+
+ String[] textValues = (String[]) textElements.get(element.getName());
+ if (textValues != null) {
+ String[] textValues2 = new String[textValues.length + 1];
+ System.arraycopy(textValues, 0, textValues2, 0, textValues.length);
+ textValues2[textValues.length] = element.getValue();
+ textValues = textValues2;
+ }
+ else {
+ textValues = new String[1];
+ textValues[0] = element.getValue();
+ }
+
+ textElements.put(element.getName(), textValues);
+ allElements.put(element.getName(), textValues);
+ }
+ else {
+
+ File tempFile = element.getFile();
+ if (tempFile.exists()) {
+ DiskFile theFile = new DiskFile(tempFile.getAbsolutePath());
+ theFile.setContentType(element.getContentType());
+ theFile.setFileName(element.getFileName());
+ theFile.setFileSize((int) tempFile.length());
+ fileElements.put(element.getName(), theFile);
+ allElements.put(element.getName(), theFile);
+ }
+ }
+ }
+ }
+ catch (UnsupportedEncodingException uee) {
+ throw new ServletException("Encoding \"ISO-8859-1\" not supported");
+ }
+
+ }
+
+ public Hashtable getAllElements() {
+ return allElements;
+ }
+
+ public Hashtable getTextElements() {
+ return textElements;
+ }
+
+ public Hashtable getFileElements() {
+ return fileElements;
+ }
+
+ /**
+ * Delete all the files uploaded
+ */
+ public void rollback() {
+ Enumeration names = fileElements.keys();
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ DiskFile theFile = (DiskFile) fileElements.get(name);
+ theFile.destroy();
+ }
+ }
+
+ /**
+ * Calls on {@link #rollback() rollback()} to delete
+ * temporary files
+ */
+ public void finish() {
+ rollback();
+ }
+
+ public void setServlet(ActionServlet servlet) {
+ this.servlet = servlet;
+ }
+
+ public void setMapping(ActionMapping mapping) {
+ this.mapping = mapping;
+ }
+
+ public ActionServlet getServlet() {
+ return servlet;
+ }
+
+ public ActionMapping getMapping() {
+ return mapping;
+ }
+
+ /**
+ * Gets the maximum post data size in bytes from the string
+ * representation in ActionServlet
+ */
+ protected long getMaxSizeFromServlet() throws ServletException{
+ String stringSize = servlet.getMaxFileSize();
+ long size = -1;
+ int multiplier = 1;
+
+ if (stringSize.endsWith("K")) {
+ multiplier = 1024;
+ stringSize = stringSize.substring(0, stringSize.length()-1);
+ }
+ if (stringSize.endsWith("M")) {
+ multiplier = 1024*1024;
+ stringSize = stringSize.substring(0, stringSize.length()-1);
+ }
+ else if (stringSize.endsWith("G")) {
+ multiplier = 1024*1024*1024;
+ stringSize = stringSize.substring(0, stringSize.length()-1);
+ }
+
+ try {
+ size = Long.parseLong(stringSize);
+ }
+ catch (NumberFormatException nfe) {
+ throw new ServletException("Invalid format for maximum file size: \"" +
+ servlet.getMaxFileSize() + "\"");
+ }
+
+ return (size * multiplier);
+ }
+
+ /**
+ * Retrieves the temporary directory from either ActionServlet, a context
+ * property, or a system property, in that order
+ */
+ protected void retrieveTempDir() {
+ //get a handle to some temporary file and open
+ //a stream to it
+ tempDir = servlet.getTempDir();
+ if (tempDir == null) {
+ //attempt to retrieve the servlet container's temporary directory
+ ServletContext context = servlet.getServletConfig().getServletContext();
+
+ try {
+ tempDir = (String) context.getAttribute("javax.servlet.context.tempdir");
+ }
+ catch (ClassCastException cce) {
+ tempDir = ((File) context.getAttribute("javax.servlet.context.tempdir")).getAbsolutePath();
+ }
+
+
+ if (tempDir == null) {
+ //default to system-wide tempdir
+ tempDir = System.getProperty("java.io.tmpdir");
+
+ if (servlet.getDebug() > 1) {
+ servlet.log("DiskMultipartRequestHandler.handleRequest(): " +
+ "defaulting to java.io.tmpdir directory \"" +
+ tempDir);
+ }
+ }
+ }
+ }
}
1.10 +547 -498 jakarta-struts/src/share/org/apache/struts/upload/MultipartIterator.java
Index: MultipartIterator.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/upload/MultipartIterator.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- MultipartIterator.java 2001/02/14 21:43:06 1.9
+++ MultipartIterator.java 2001/04/11 22:56:20 1.10
@@ -1,498 +1,547 @@
-package org.apache.struts.upload;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.FileOutputStream;
-import java.io.UnsupportedEncodingException;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * The MultipartIterator class is responsible for reading the
- * input data of a multipart request and splitting it up into
- * input elements, wrapped inside of a
- * {@link org.apache.struts.upload.MultipartElement MultipartElement}
- * for easy definition. To use this class, create a new instance
- * of MultipartIterator passing it a HttpServletRequest in the
- * constructor. Then use the {@link #getNextElement() getNextElement}
- * method until it returns null, then you're finished. Example: <br>
- * <pre>
- * MultipartIterator iterator = new MultipartIterator(request);
- * MultipartElement element;
- *
- * while ((element = iterator.getNextElement()) != null) {
- * //do something with element
- * }
- * </pre>
- *
- * @see org.apache.struts.upload.MultipartElement
- * @author Mike Schachter
- */
-public class MultipartIterator {
-
- /**
- * The request instance for this class
- */
- protected HttpServletRequest request;
-
- /**
- * The input stream instance for this class
- */
- protected ServletInputStream inputStream;
-
- /**
- * The boundary for this multipart request
- */
- protected String boundary;
-
- /**
- * Whether or not the input stream is finished
- */
- protected boolean contentRead = false;
-
- /**
- * The maximum file size in bytes allowed. Ignored if -1
- */
- protected long maxSize = -1;
-
- /**
- * The total bytes read from this request
- */
- protected long totalLength = 0;
-
- /**
- * The content length of this request
- */
- protected int contentLength;
-
- /**
- * The amount of data read from a request at a time.
- * This also represents the maximum size in bytes of
- * a line read from the request
- * Defaults to 4 * 1024 (4 KB)
- */
- protected int bufferSize = 4 * 1024;
-
- /**
- * The temporary directory to store files
- */
- protected String tempDir;
-
- /**
- * Constructs a MultipartIterator with a default buffer size and no file size
- * limit
- *
- * @param request The multipart request to iterate
- */
- public MultipartIterator(HttpServletRequest request) throws ServletException{
- this(request, -1);
- }
-
- /**
- * Constructs a MultipartIterator with the specified buffer size and
- * no file size limit
- *
- * @param request The multipart request to iterate
- * @param bufferSize The size in bytes that should be read from the input
- * stream at a times
- */
- public MultipartIterator(HttpServletRequest request, int bufferSize) throws ServletException {
- this (request, bufferSize, -1);
- }
-
- /**
- * Constructs a MultipartIterator with the specified buffer size and
- * the specified file size limit in bytes
- *
- * @param request The multipart request to iterate
- * @param bufferSize The size in bytes that should be read from the input
- * stream at a times
- * @param maxSize The maximum size in bytes allowed for a multipart element's data
- */
- public MultipartIterator(HttpServletRequest request, int bufferSize, long maxSize)
- throws ServletException {
-
- this(request, bufferSize, maxSize, null);
-
- }
-
- public MultipartIterator(HttpServletRequest request,
- int bufferSize,
- long maxSize,
- String tempDir) throws ServletException {
-
- this.request = request;
- this.maxSize = maxSize;
- if (bufferSize > -1) {
- this.bufferSize = bufferSize;
- }
- if (tempDir != null) {
- this.tempDir = tempDir;
- }
- else {
- //default to system-wide tempdir
- tempDir = System.getProperty("java.io.tmpdir");
- }
- parseRequest();
- }
-
- /**
- * Retrieves the next element in the iterator if one exists.
- *
- * @throws a ServletException if the post size exceeds the maximum file size
- * passed in the 3 argument constructor
- * @throws an UnsupportedEncodingException if the "ISO-8859-1" encoding isn't found
- * @return a {@link org.apache.struts.upload.MultipartElement MultipartElement}
- * representing the next element in the request data
- *
- */
- public MultipartElement getNextElement() throws ServletException, UnsupportedEncodingException {
- //retrieve the "Content-Disposition" header
- //and parse
- String disposition = readLine();
-
- if ((disposition != null) && (disposition.startsWith("Content-Disposition"))) {
- String name = parseDispositionName(disposition);
- String filename = parseDispositionFilename(disposition);
-
- String contentType = null;
- boolean isFile = (filename != null);
-
- if (isFile) {
- filename = new File(filename).getName();
-
- //check for windows filenames,
- //from linux jdk's the entire filepath
- //isn't parsed correctly from File.getName()
- int colonIndex = filename.indexOf(":");
- int slashIndex = filename.lastIndexOf("\\");
-
- if ((colonIndex > -1) && (slashIndex > -1)) {
- //then consider this filename to be a full
- //windows filepath, and parse it accordingly
- //to retrieve just the file name
- filename = filename.substring(slashIndex+1, filename.length());
- }
-
-
-
- //get the content type
- contentType = readLine();
- contentType = parseContentType(contentType);
- }
-
-
-
- //ignore next line (whitespace) (unless it's a file
- //without content-type)
- if (! ((isFile) && contentType == null)) {
- readLine();
- }
-
- MultipartElement element = null;
-
- //process a file element
- if (isFile) {
- try {
- //create a local file on disk representing the element
- File elementFile = createLocalFile();
-
- element = new MultipartElement(name, filename, contentType, elementFile);
- } catch (IOException ioe) {
- throw new ServletException("IOException while reading file element: ioe.getMessage()", ioe);
- }
- }
- else {
- //read data into String form, then convert to bytes
- //for text
- StringBuffer textData = new StringBuffer();
- String line;
- //parse for text data
- line = readLine();
-
- while ((line != null) && (!line.startsWith(boundary))) {
- textData.append(line);
- line = readLine();
-
- if (maxSize > -1) {
- if (totalLength > maxSize) {
- throw new ServletException("Multipart data size exceeds the maximum " +
- "allowed post size");
- }
- }
- }
-
- if (textData.length() > 1) {
- //cut off "\r\n" from the end
- textData.setLength(textData.length()-2);
- }
-
- //create the element
- element = new MultipartElement(name, textData.toString());
- }
- return element;
- }
- //reset stream
- if (inputStream.markSupported()) {
- try {
- inputStream.reset();
- }
- catch (IOException ioe) {
- throw new ServletException("IOException while resetting input stream: " +
- ioe.getMessage());
- }
- }
- return null;
- }
-
- /**
- * Set the maximum amount of bytes read from a line at one time
- *
- * @see javax.servlet.ServletInputStream#readLine(byte[], int, int)
- */
- public void setBufferSize(int bufferSize) {
- this.bufferSize = bufferSize;
- }
-
- /**
- * Get the maximum amount of bytes read from a line at one time
- *
- * @see javax.servlet.ServletInputStream#readLine(byte[], int, int)
- */
- public int getBufferSize() {
- return bufferSize;
- }
-
- /**
- * Set the maximum post data size allowed for a multipart request
- * @param maxSize The maximum post data size in bytes, set to <code>-1</code>
- * for no limit
- */
- public void setMaxSize(long maxSize) {
- this.maxSize = maxSize;
- }
-
- /**
- * Get the maximum post data size allowed for a multipart request
- * @return The maximum post data size in bytes
- */
- public long getMaxSize() {
- return maxSize;
- }
-
- /**
- * Handles retrieving the boundary and setting the input stream
- */
- protected void parseRequest() throws ServletException {
-
- contentLength = request.getContentLength();
-
- //set boundary
- boundary = parseBoundary(request.getContentType());
-
- try {
- //set the input stream
- inputStream = request.getInputStream();
- //mark the input stream to allow multiple reads
- if (inputStream.markSupported()) {
- inputStream.mark(contentLength+1);
- }
-
- }
- catch (IOException ioe) {
- throw new ServletException("MultipartIterator.parseRequest(): " +
- "IOException while trying to obtain " +
- "ServletInputStream");
- }
-
- if ((boundary == null) || (boundary.length() < 1)) {
- //try retrieving the header through more "normal" means
- boundary = parseBoundary(request.getHeader("Content-type"));
- }
-
- if ((boundary == null) || (boundary.length() < 1)) {
- throw new ServletException("MultipartIterator: cannot retrieve boundary " +
- "for multipart request");
- }
-
- //read first line
- try {
- String firstLine = readLine();
-
- if (firstLine == null) {
- throw new ServletException("MultipartIterator: no multipart request data " +
- "sent");
- }
- if (!firstLine.startsWith(boundary)) {
- throw new ServletException("MultipartIterator: invalid multipart request " +
- "data, doesn't start with boundary");
- }
- }
- catch (UnsupportedEncodingException uee) {
- throw new ServletException("MultipartIterator: encoding \"ISO-8859-1\" not supported");
- }
- }
-
- /**
- * Parses a content-type String for the boundary. Appends a
- * "--" to the beginning of the boundary, because thats the
- * real boundary as opposed to the shortened one in the
- * content type.
- */
- public static String parseBoundary(String contentType) {
- if (contentType.lastIndexOf("boundary=") != -1) {
- String _boundary = "--" +
- contentType.substring(contentType.lastIndexOf("boundary=")+9);
- if (_boundary.endsWith("\n")) {
- //strip it off
- return _boundary.substring(0, _boundary.length()-1);
- }
- return _boundary;
- }
- return null;
- }
-
- /**
- * Parses the "Content-Type" line of a multipart form for a content type
- *
- * @param contentTypeString A String reprsenting the Content-Type line,
- * with a trailing "\n"
- * @return The content type specified, or <code>null</code> if one can't be
- * found.
- */
- public static String parseContentType(String contentTypeString) {
- int nameIndex = contentTypeString.indexOf("Content-Type: ");
-
- if (nameIndex != -1) {
- int endLineIndex = contentTypeString.indexOf("\n");
- if (endLineIndex != -1) {
- return contentTypeString.substring(nameIndex+14, endLineIndex);
- }
- }
- return null;
- }
-
- /**
- * Retrieves the "name" attribute from a content disposition line
- *
- * @param dispositionString The entire "Content-disposition" string
- * @return <code>null</code> if no name could be found, otherwise,
- * returns the name
- * @see #parseForAttribute(String, String)
- */
- public static String parseDispositionName(String dispositionString) {
- return parseForAttribute("name", dispositionString);
- }
-
- /**
- * Retrieves the "filename" attribute from a content disposition line
- *
- * @param dispositionString The entire "Content-disposition" string
- * @return <code>null</code> if no filename could be found, otherwise,
- * returns the filename
- * @see #parseForAttribute(String, String)
- */
- public static String parseDispositionFilename(String dispositionString) {
- return parseForAttribute("filename", dispositionString);
- }
-
-
- /**
- * Parses a string looking for a attribute-value pair, and returns the value.
- * For example:
- * <pre>
- * String parseString = "Content-Disposition: filename=\"bob\" name=\"jack\"";
- * MultipartIterator.parseForAttribute(parseString, "name");
- * </pre>
- * That will return "bob".
- *
- * @param attribute The name of the attribute you're trying to get
- * @param parseString The string to retrieve the value from
- * @return The value of the attribute, or <code>null</code> if none could be found
- */
- public static String parseForAttribute(String attribute, String parseString) {
- int nameIndex = parseString.indexOf(attribute + "=\"");
- if (nameIndex != -1) {
-
- int endQuoteIndex = parseString.indexOf("\"", nameIndex+attribute.length()+3);
-
- if (endQuoteIndex != -1) {
- return parseString.substring(nameIndex+attribute.length()+2, endQuoteIndex);
- }
- return "";
- }
- return null;
- }
-
- /**
- * Reads the input stream until it reaches a new line
- */
- protected String readLine() throws ServletException, UnsupportedEncodingException {
-
- byte[] bufferByte = new byte[bufferSize];
- int bytesRead;
-
- if (totalLength >= contentLength) {
- return null;
- }
-
- try {
- bytesRead = inputStream.readLine(bufferByte,
- 0,
- bufferSize);
- }
- catch (IOException ioe) {
- throw new ServletException("IOException while reading multipart request: " +
- ioe.getMessage());
- }
- if (bytesRead == -1) {
- return null;
- }
-
- totalLength += bytesRead;
- return new String(bufferByte, 0, bytesRead, "ISO-8859-1");
- }
-
- /**
- * Creates a file on disk from the current mulitpart element
- * @param fileName the name of the multipart file
- */
- protected File createLocalFile() throws IOException,ServletException {
-
- File tempFile = File.createTempFile("strts", null, new File(tempDir));
- OutputStream fos = new FileOutputStream(tempFile);
-
- byte[] bufferBytes = new byte[bufferSize];
- InputStream requestIn = new MultipartValueStream(inputStream, boundary);
-
- int bytesRead = 0;
- while (bytesRead != -1) {
-
- bytesRead = requestIn.read(bufferBytes);
-
- if (bytesRead > 0) {
- totalLength += bytesRead;
- }
-
- //check to make sure the read doesn't exceed the bounds
- if (bytesRead > 0) {
- if (maxSize > -1) {
- if (totalLength > maxSize) {
- throw new ServletException("Multipart data size exceeds the maximum " +
- "allowed post size");
- }
- }
- }
- if (bytesRead > 0) {
- fos.write(bufferBytes, 0, bytesRead);
- }
- }
-
- fos.close();
- return tempFile;
- }
-
-}
+package org.apache.struts.upload;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.UnsupportedEncodingException;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * The MultipartIterator class is responsible for reading the
+ * input data of a multipart request and splitting it up into
+ * input elements, wrapped inside of a
+ * {@link org.apache.struts.upload.MultipartElement MultipartElement}
+ * for easy definition. To use this class, create a new instance
+ * of MultipartIterator passing it a HttpServletRequest in the
+ * constructor. Then use the {@link #getNextElement() getNextElement}
+ * method until it returns null, then you're finished. Example: <br>
+ * <pre>
+ * MultipartIterator iterator = new MultipartIterator(request);
+ * MultipartElement element;
+ *
+ * while ((element = iterator.getNextElement()) != null) {
+ * //do something with element
+ * }
+ * </pre>
+ *
+ * @see org.apache.struts.upload.MultipartElement
+ * @author Mike Schachter
+ */
+public class MultipartIterator {
+
+ /**
+ * The maximum size in bytes of the buffer used to read lines [4K]
+ */
+ public static int MAX_LINE_SIZE = 4096;
+
+ /**
+ * The request instance for this class
+ */
+ protected HttpServletRequest request;
+
+ /**
+ * The input stream instance for this class
+ */
+ protected BufferedMultipartInputStream inputStream;
+
+ /**
+ * The boundary for this multipart request
+ */
+ protected String boundary;
+
+ /**
+ * The byte array representing the boundary for this multipart request
+ */
+ protected byte[] boundaryBytes;
+
+ /**
+ * Whether or not the input stream is finished
+ */
+ protected boolean contentRead = false;
+
+ /**
+ * The maximum file size in bytes allowed. Ignored if -1
+ */
+ protected long maxSize = -1;
+
+ /**
+ * The total bytes read from this request
+ */
+ protected long totalLength = 0;
+
+ /**
+ * The content length of this request
+ */
+ protected int contentLength;
+
+ /**
+ * The size in bytes written to the filesystem at a time [20K]
+ */
+ protected int diskBufferSize = 2 * 10240;
+
+ /**
+ * The amount of data read from a request at a time.
+ * This also represents the maximum size in bytes of
+ * a line read from the request [4KB]
+ */
+ protected int bufferSize = 4096;
+
+ /**
+ * The temporary directory to store files
+ */
+ protected String tempDir;
+
+ /**
+ * Constructs a MultipartIterator with a default buffer size and no file size
+ * limit
+ *
+ * @param request The multipart request to iterate
+ */
+ public MultipartIterator(HttpServletRequest request) throws ServletException{
+ this(request, -1);
+ }
+
+ /**
+ * Constructs a MultipartIterator with the specified buffer size and
+ * no file size limit
+ *
+ * @param request The multipart request to iterate
+ * @param bufferSize The size in bytes that should be read from the input
+ * stream at a times
+ */
+ public MultipartIterator(HttpServletRequest request, int bufferSize) throws ServletException {
+ this (request, bufferSize, -1);
+ }
+
+ /**
+ * Constructs a MultipartIterator with the specified buffer size and
+ * the specified file size limit in bytes
+ *
+ * @param request The multipart request to iterate
+ * @param bufferSize The size in bytes that should be read from the input
+ * stream at a times
+ * @param maxSize The maximum size in bytes allowed for a multipart element's data
+ */
+ public MultipartIterator(HttpServletRequest request, int bufferSize, long maxSize)
+ throws ServletException {
+
+ this(request, bufferSize, maxSize, null);
+
+ }
+
+ public MultipartIterator(HttpServletRequest request,
+ int bufferSize,
+ long maxSize,
+ String tempDir) throws ServletException {
+
+ this.request = request;
+ this.maxSize = maxSize;
+ if (bufferSize > -1) {
+ this.bufferSize = bufferSize;
+ }
+ if (tempDir != null) {
+ this.tempDir = tempDir;
+ }
+ else {
+ //default to system-wide tempdir
+ tempDir = System.getProperty("java.io.tmpdir");
+ }
+ parseRequest();
+ }
+
+ /**
+ * Retrieves the next element in the iterator if one exists.
+ *
+ * @throws a ServletException if the post size exceeds the maximum file size
+ * passed in the 3 argument constructor
+ * @throws an UnsupportedEncodingException if the "ISO-8859-1" encoding isn't found
+ * @return a {@link org.apache.struts.upload.MultipartElement MultipartElement}
+ * representing the next element in the request data
+ *
+ */
+ public MultipartElement getNextElement() throws ServletException, UnsupportedEncodingException {
+ //retrieve the "Content-Disposition" header
+ //and parse
+ String disposition = readLine();
+
+
+ if ((disposition != null) && (disposition.startsWith("Content-Disposition"))) {
+ String name = parseDispositionName(disposition);
+ String filename = parseDispositionFilename(disposition);
+
+ String contentType = null;
+ boolean isFile = (filename != null);
+
+ if (isFile) {
+ filename = new File(filename).getName();
+
+ //check for windows filenames,
+ //from linux jdk's the entire filepath
+ //isn't parsed correctly from File.getName()
+ int colonIndex = filename.indexOf(":");
+ int slashIndex = filename.lastIndexOf("\\");
+
+ if ((colonIndex > -1) && (slashIndex > -1)) {
+ //then consider this filename to be a full
+ //windows filepath, and parse it accordingly
+ //to retrieve just the file name
+ filename = filename.substring(slashIndex+1, filename.length());
+ }
+
+ //get the content type
+ contentType = readLine();
+ contentType = parseContentType(contentType);
+ }
+
+
+
+ //ignore next line (whitespace) (unless it's a file
+ //without content-type)
+ if (! ((isFile) && contentType == null)) {
+ readLine();
+ }
+
+ MultipartElement element = null;
+
+ //process a file element
+ if (isFile) {
+ try {
+ //create a local file on disk representing the element
+ File elementFile = createLocalFile();
+
+ element = new MultipartElement(name, filename, contentType, elementFile);
+ } catch (IOException ioe) {
+ throw new ServletException("IOException while reading file element: ioe.getMessage()", ioe);
+ }
+ }
+ else {
+ //read data into String form, then convert to bytes
+ //for text
+ StringBuffer textData = new StringBuffer();
+ String line;
+ //parse for text data
+ line = readLine();
+
+ while ((line != null) && (!line.startsWith(boundary))) {
+ textData.append(line);
+ line = readLine();
+
+ if (maxSize > -1) {
+ if (totalLength > maxSize) {
+ throw new ServletException("Multipart data size exceeds the maximum " +
+ "allowed post size");
+ }
+ }
+ }
+
+ if (textData.length() > 0) {
+ //cut off "\r" from the end if necessary
+ if (textData.charAt(textData.length()-1) == '\r') {
+ textData.setLength(textData.length()-1);
+ }
+ }
+
+ //create the element
+ element = new MultipartElement(name, textData.toString());
+ }
+ return element;
+ }
+
+ //reset stream
+ if (inputStream.markSupported()) {
+ try {
+ inputStream.reset();
+ }
+ catch (IOException ioe) {
+ throw new ServletException("IOException while resetting input stream: " +
+ ioe.getMessage());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Set the maximum amount of bytes read from a line at one time
+ *
+ * @see javax.servlet.ServletInputStream#readLine(byte[], int, int)
+ */
+ public void setBufferSize(int bufferSize) {
+ this.bufferSize = bufferSize;
+ }
+
+ /**
+ * Get the maximum amount of bytes read from a line at one time
+ *
+ * @see javax.servlet.ServletInputStream#readLine(byte[], int, int)
+ */
+ public int getBufferSize() {
+ return bufferSize;
+ }
+
+ /**
+ * Set the maximum post data size allowed for a multipart request
+ * @param maxSize The maximum post data size in bytes, set to <code>-1</code>
+ * for no limit
+ */
+ public void setMaxSize(long maxSize) {
+ this.maxSize = maxSize;
+ }
+
+ /**
+ * Get the maximum post data size allowed for a multipart request
+ * @return The maximum post data size in bytes
+ */
+ public long getMaxSize() {
+ return maxSize;
+ }
+
+ /**
+ * Handles retrieving the boundary and setting the input stream
+ */
+ protected void parseRequest() throws ServletException {
+
+ contentLength = request.getContentLength();
+
+ //set boundary
+ boundary = parseBoundary(request.getContentType());
+ boundaryBytes = boundary.getBytes();
+
+ try {
+ //set the input stream
+ inputStream = new BufferedMultipartInputStream(request.getInputStream(),
+ bufferSize,
+ contentLength,
+ maxSize);
+ //mark the input stream to allow multiple reads
+ if (inputStream.markSupported()) {
+ inputStream.mark(contentLength+1);
+ }
+
+ }
+ catch (IOException ioe) {
+ throw new ServletException("MultipartIterator.parseRequest(): " +
+ "IOException while trying to obtain " +
+ "ServletInputStream");
+ }
+
+ if ((boundary == null) || (boundary.length() < 1)) {
+ //try retrieving the header through more "normal" means
+ boundary = parseBoundary(request.getHeader("Content-type"));
+ }
+
+ if ((boundary == null) || (boundary.length() < 1)) {
+ throw new ServletException("MultipartIterator: cannot retrieve boundary " +
+ "for multipart request");
+ }
+
+ //read first line
+ try {
+ String firstLine = readLine();
+
+ if (firstLine == null) {
+ throw new ServletException("MultipartIterator: no multipart request data " +
+ "sent");
+ }
+ if (!firstLine.startsWith(boundary)) {
+ throw new ServletException("MultipartIterator: invalid multipart request " +
+ "data, doesn't start with boundary");
+ }
+ }
+ catch (UnsupportedEncodingException uee) {
+ throw new ServletException("MultipartIterator: encoding \"ISO-8859-1\" not supported");
+ }
+ }
+
+ /**
+ * Parses a content-type String for the boundary. Appends a
+ * "--" to the beginning of the boundary, because thats the
+ * real boundary as opposed to the shortened one in the
+ * content type.
+ */
+ public static String parseBoundary(String contentType) {
+ if (contentType.lastIndexOf("boundary=") != -1) {
+ String _boundary = "--" +
+ contentType.substring(contentType.lastIndexOf("boundary=")+9);
+ if (_boundary.endsWith("\n")) {
+ //strip it off
+ return _boundary.substring(0, _boundary.length()-1);
+ }
+ return _boundary;
+ }
+ return null;
+ }
+
+ /**
+ * Parses the "Content-Type" line of a multipart form for a content type
+ *
+ * @param contentTypeString A String reprsenting the Content-Type line,
+ * with a trailing "\n"
+ * @return The content type specified, or <code>null</code> if one can't be
+ * found.
+ */
+ public static String parseContentType(String contentTypeString) {
+ int nameIndex = contentTypeString.indexOf("Content-Type: ");
+
+ if (nameIndex != -1) {
+ int endLineIndex = contentTypeString.indexOf("\n");
+ if (endLineIndex == -1) {
+ endLineIndex = contentTypeString.length()-1;
+ }
+ return contentTypeString.substring(nameIndex+14, endLineIndex);
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves the "name" attribute from a content disposition line
+ *
+ * @param dispositionString The entire "Content-disposition" string
+ * @return <code>null</code> if no name could be found, otherwise,
+ * returns the name
+ * @see #parseForAttribute(String, String)
+ */
+ public static String parseDispositionName(String dispositionString) {
+ return parseForAttribute("name", dispositionString);
+ }
+
+ /**
+ * Retrieves the "filename" attribute from a content disposition line
+ *
+ * @param dispositionString The entire "Content-disposition" string
+ * @return <code>null</code> if no filename could be found, otherwise,
+ * returns the filename
+ * @see #parseForAttribute(String, String)
+ */
+ public static String parseDispositionFilename(String dispositionString) {
+ return parseForAttribute("filename", dispositionString);
+ }
+
+
+ /**
+ * Parses a string looking for a attribute-value pair, and returns the value.
+ * For example:
+ * <pre>
+ * String parseString = "Content-Disposition: filename=\"bob\" name=\"jack\"";
+ * MultipartIterator.parseForAttribute(parseString, "name");
+ * </pre>
+ * That will return "bob".
+ *
+ * @param attribute The name of the attribute you're trying to get
+ * @param parseString The string to retrieve the value from
+ * @return The value of the attribute, or <code>null</code> if none could be found
+ */
+ public static String parseForAttribute(String attribute, String parseString) {
+ int nameIndex = parseString.indexOf(attribute + "=\"");
+ if (nameIndex != -1) {
+
+ int endQuoteIndex = parseString.indexOf("\"", nameIndex+attribute.length()+3);
+
+ if (endQuoteIndex != -1) {
+ return parseString.substring(nameIndex+attribute.length()+2, endQuoteIndex);
+ }
+ return "";
+ }
+ return null;
+ }
+
+ /**
+ * Reads the input stream until it reaches a new line
+ */
+ protected String readLine() throws ServletException, UnsupportedEncodingException {
+
+ byte[] bufferByte = new byte[bufferSize];
+ int bytesRead;
+
+ if (totalLength >= contentLength) {
+ return null;
+ }
+
+ try {
+ bytesRead = inputStream.readLine(bufferByte,
+ 0,
+ bufferSize);
+ }
+ catch (IOException ioe) {
+ throw new ServletException("IOException while reading multipart request: " +
+ ioe.getMessage());
+ }
+ if (bytesRead == -1) {
+ return null;
+ }
+
+ totalLength += bytesRead;
+ return new String(bufferByte, 0, bytesRead, "ISO-8859-1");
+ }
+
+ /**
+ * Creates a file on disk from the current mulitpart element
+ * @param fileName the name of the multipart file
+ */
+ protected File createLocalFile() throws IOException {
+
+ File tempFile = File.createTempFile("strts", null, new File(tempDir));
+ BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile),
+ diskBufferSize);
+ byte[] lineBuffer = new byte[MAX_LINE_SIZE];
+ int bytesRead = inputStream.readLine(lineBuffer, 0, MAX_LINE_SIZE);
+
+ boolean cutCarriage = false;
+ boolean cutNewline = false;
+
+ while ((bytesRead != -1) && (!equals(lineBuffer, 0, boundaryBytes.length,
+ boundaryBytes))) {
+
+ if (cutCarriage) {
+ fos.write('\r');
+ }
+ if (cutNewline) {
+ fos.write('\n');
+ }
+ if (bytesRead > 0) {
+ if (lineBuffer[bytesRead-1] == '\r') {
+ bytesRead--;
+ cutCarriage = true;
+ }
+ else {
+ cutCarriage = false;
+ }
+ }
+ cutNewline = true;
+ fos.write(lineBuffer, 0, bytesRead);
+ bytesRead = inputStream.readLine(lineBuffer, 0, MAX_LINE_SIZE);
+ }
+
+ fos.flush();
+ fos.close();
+ return tempFile;
+ }
+
+ /**
+ * Checks bytes for equality. Two byte arrays are equal if
+ * each of their elements are the same. This method checks
+ * comp[offset] with source[0] to source[length-1] with
+ * comp[offset + length - 1]
+ * @param comp The byte to compare to <code>source</code>
+ * @param offset The offset to start at in <code>comp</code>
+ * @param length The length of <code>comp</code> to compare to
+ * @param source The reference byte to test for equality
+ */
+ public static boolean equals(byte[] comp, int offset, int length,
+ byte[] source) {
+
+ if (length != source.length) {
+ return false;
+ }
+
+ for (int i = 0; i < length; i++) {
+ if (comp[offset+i] != source[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
1.1 jakarta-struts/src/share/org/apache/struts/upload/BufferedMultipartInputStream.java
Index: BufferedMultipartInputStream.java
===================================================================
package org.apache.struts.upload;
import java.io.IOException;
import java.io.InputStream;
/**
* This class implements buffering for an InputStream as well as a
* readLine method. The purpose of this is to provide a reliable
* readLine() method.
*/
public class BufferedMultipartInputStream extends InputStream {
/**
* The underlying InputStream used by this class
*/
protected InputStream inputStream;
/**
* The byte array used to hold buffered data
*/
protected byte[] buffer;
/**
* The current offset we're at in the buffer's byte array
*/
protected int bufferOffset = 0;
/**
* The size of the byte array buffer
*/
protected int bufferSize = 8192;
/**
* The number of bytes read from the underlying InputStream that are
* in the buffer
*/
protected int bufferLength = 0;
/**
* The total number of bytes read so far
*/
protected int totalLength = 0;
/**
* The content length of the multipart data
*/
protected long contentLength;
/**
* The maximum allowed size for the multipart data, or -1 for an unlimited
* maximum file length
*/
protected long maxSize = -1;
/**
* Public constructor for this class, just wraps the InputStream
* given
* @param inputStream The underlying stream to read from
* @param bufferSize The size in bytes of the internal buffer
* @param contentLength The content length for this request
* @param maxSize The maximum size in bytes that this multipart
* request can be, or -1 for an unlimited length
*/
public BufferedMultipartInputStream(InputStream inputStream,
int bufferSize,
long contentLength,
long maxSize) throws IOException {
this.inputStream = inputStream;
this.bufferSize = bufferSize;
this.contentLength = contentLength;
this.maxSize = maxSize;
buffer = new byte[bufferSize];
fill();
}
/**
* This method returns the number of available bytes left to read
* in the buffer before it has to be refilled
*/
public int available() {
return bufferLength - bufferOffset;
}
/**
* This method attempts to close the underlying InputStream
*/
public void close() throws IOException {
inputStream.close();
}
/**
* This method calls on the mark() method of the underlying InputStream
*/
public void mark(int position) {
inputStream.mark(position);
}
/**
* This method calls on the markSupported() method of the underlying InputStream
* @return Whether or not the underlying InputStream supports marking
*/
public boolean markSupported() {
return inputStream.markSupported();
}
/**
* This method returns the next byte in the buffer, and refills it if necessary.
* @return The next byte read in the buffer, or -1 if the end of the stream has
* been reached
*/
public int read() throws IOException {
if (buffer == null) {
return -1;
}
if (bufferOffset < bufferLength) {
return (int)(char) buffer[bufferOffset++];
}
fill();
return read();
}
/**
* This method populates the byte array <code>b</code> with data up to
* <code>b.length</code> bytes
*/
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
/**
* This method populates the byte array <code>b</code> with data up to
* <code>length</code> starting at b[offset]
*/
public int read(byte[] b, int offset, int length) throws IOException {
int count = 0;
int read = read();
if (read == -1) {
return -1;
}
while ((read != -1) && (count < length)) {
b[offset] = (byte) read;
read = read();
count++;
offset++;
}
return count;
}
/**
* This method reads into the byte array <code>b</code> until
* a newline ('\n') character is encountered or the number of bytes
* specified by <code>length</code> have been read
*/
public int readLine(byte[] b, int offset, int length) throws IOException {
int count = 0;
int read = read();
if (read == -1) {
return -1;
}
while ((read != -1) && (count < length)) {
if (read == '\n')
break;
b[offset] = (byte) read;
count++;
offset++;
read = read();
}
return count;
}
/**
* This method makes a call to the reset() method of the underlying
* InputStream
*/
public void reset() throws IOException {
inputStream.reset();
}
/**
* Fills the buffer with data from the underlying inputStream. If it can't
* fill the entire buffer in one read, it will read as many times as necessary
* to fill the buffer
*/
protected void fill() throws IOException {
if ((bufferOffset > -1) && (bufferLength > -1)) {
int length = Math.min(bufferSize, (int) contentLength);
if (maxSize > -1) {
length = Math.min(length, (int) maxSize);
}
int bytesRead = inputStream.read(buffer, 0, length);
if (bytesRead == -1) {
buffer = null;
bufferOffset = -1;
bufferLength = -1;
}
else {
bufferLength = bytesRead;
totalLength += bytesRead;
bufferOffset = 0;
}
}
}
}
1.2 +37 -8 jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadAction.java
Index: UploadAction.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadAction.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UploadAction.java 2001/03/22 13:17:10 1.1
+++ UploadAction.java 2001/04/11 22:56:23 1.2
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadAction.java,v 1.1 2001/03/22 13:17:10 rleland Exp $
- * $Revision: 1.1 $
- * $Date: 2001/03/22 13:17:10 $
+ * $Header: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadAction.java,v 1.2 2001/04/11 22:56:23 mschachter Exp $
+ * $Revision: 1.2 $
+ * $Date: 2001/04/11 22:56:23 $
*
* ====================================================================
*
@@ -64,6 +64,8 @@
import java.io.InputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
@@ -85,7 +87,7 @@
* page to display them
*
* @author Mike Schachter
- * @version $Revision: 1.1 $ $Date: 2001/03/22 13:17:10 $
+ * @version $Revision: 1.2 $ $Date: 2001/04/11 22:56:23 $
*/
@@ -111,6 +113,8 @@
//retrieve the content type
String contentType = file.getContentType();
+
+ boolean writeFile = theForm.getWriteFile();
//retrieve the file size
String size = (file.getFileSize() + " bytes");
@@ -120,12 +124,37 @@
try {
//retrieve the file data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
InputStream stream = file.getInputStream();
- byte[] buffer = new byte[file.getFileSize()];
- stream.read(buffer);
- baos.write(buffer);
- data = new String(baos.toByteArray());
+ if (!writeFile) {
+ //only write files out that are less than 1MB
+ if (file.getFileSize() < (4*1024000)) {
+
+ byte[] buffer = new byte[8192];
+ int bytesRead = 0;
+ while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
+ baos.write(buffer, 0, bytesRead);
+ }
+ data = new String(baos.toByteArray());
+ }
+ else {
+ data = new String("The file is greater than 4MB, " +
+ " and has not been written to stream." +
+ " File Size: " + file.getFileSize() + " bytes. This is a" +
+ " limitation of this particular web application, hard-coded" +
+ " in org.apache.struts.upload.UploadAction");
+ }
+ }
+ else {
+ //write the file to the file specified
+ OutputStream bos = new FileOutputStream(theForm.getFilePath());
+ int bytesRead = 0;
+ byte[] buffer = new byte[8192];
+ while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
+ bos.write(buffer, 0, bytesRead);
+ }
+ bos.close();
+ data = "The file has been written to \"" + theForm.getFilePath() + "\"";
+ }
}
catch (FileNotFoundException fnfe) {
return null;
1.2 +45 -3 jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadForm.java
Index: UploadForm.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadForm.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UploadForm.java 2001/03/22 13:17:10 1.1
+++ UploadForm.java 2001/04/11 22:56:24 1.2
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadForm.java,v 1.1 2001/03/22 13:17:10 rleland Exp $
- * $Revision: 1.1 $
- * $Date: 2001/03/22 13:17:10 $
+ * $Header: /home/cvs/jakarta-struts/src/upload/org/apache/struts/webapp/upload/UploadForm.java,v 1.2 2001/04/11 22:56:24 mschachter Exp $
+ * $Revision: 1.2 $
+ * $Date: 2001/04/11 22:56:24 $
*
* ====================================================================
*
@@ -74,7 +74,7 @@
* that struts uses is org.apache.struts.upload.DiskMultipartRequestHandler.
*
* @author Mike Schachter
- * @version $Revision: 1.1 $ $Date: 2001/03/22 13:17:10 $
+ * @version $Revision: 1.2 $ $Date: 2001/04/11 22:56:24 $
*/
public class UploadForm extends ActionForm {
@@ -83,11 +83,21 @@
* The value of the text the user has sent as form data
*/
protected String theText;
+
+ /**
+ * Whether or not to write to a file
+ */
+ protected boolean writeFile;
/**
* The file that the user has uploaded
*/
protected FormFile theFile;
+
+ /**
+ * The file path to write to
+ */
+ protected String filePath;
@@ -117,5 +127,37 @@
*/
public void setTheFile(FormFile theFile) {
this.theFile = theFile;
+ }
+
+ /**
+ * Set whether or not to write to a file
+ */
+ public void setWriteFile(boolean writeFile) {
+ this.writeFile = writeFile;
+ }
+
+ /**
+ * Get whether or not to write to a file
+ */
+ public boolean getWriteFile() {
+ return writeFile;
+ }
+
+ /**
+ * Set the path to write a file to
+ */
+ public void setFilePath(String filePath) {
+ this.filePath = filePath;
+ }
+
+ /**
+ * Get the path to write a file to
+ */
+ public String getFilePath() {
+ return filePath;
+ }
+
+ public void reset() {
+ writeFile = false;
}
}
1.2 +14 -14 jakarta-struts/web/upload/display.jsp
Index: display.jsp
===================================================================
RCS file: /home/cvs/jakarta-struts/web/upload/display.jsp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- display.jsp 2000/12/19 19:23:05 1.1
+++ display.jsp 2001/04/11 22:56:27 1.2
@@ -1,15 +1,15 @@
-<%@ page language="java" %>
-
-<b>The Text</b>: <%= request.getAttribute("text") %> <br />
-
-<b>The File name</b>: <%= request.getAttribute("fileName") %> <br />
-
-<b>The File content type</b>: <%= request.getAttribute("contentType") %> <br />
-
-<b>The File size</b>: <%= request.getAttribute("size") %> <br />
-
-<b>The File data</b>: <br />
-
-<hr />
-<pre><%= request.getAttribute("data") %></pre>
+<%@ page language="java" %>
+
+<b>The Text</b>: <%= request.getAttribute("text") %> <br />
+
+<b>The File name</b>: <%= request.getAttribute("fileName") %> <br />
+
+<b>The File content type</b>: <%= request.getAttribute("contentType") %> <br />
+
+<b>The File size</b>: <%= request.getAttribute("size") %> <br />
+
+<b>The File data</b>: <br />
+
+<hr />
+<pre><%= request.getAttribute("data") %></pre>
<hr />
1.3 +6 -0 jakarta-struts/web/upload/upload.jsp
Index: upload.jsp
===================================================================
RCS file: /home/cvs/jakarta-struts/web/upload/upload.jsp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- upload.jsp 2001/01/07 00:16:29 1.2
+++ upload.jsp 2001/04/11 22:56:28 1.3
@@ -15,6 +15,12 @@
Please select the file that you would like to upload:<br />
<html:file property="theFile" /><br /><br />
+
+ If you would rather write this file to another file, please check here:
+ <html:checkbox property="writeFile" /><br /><br />
+
+ If you checked the box to write to a file, please specify the file path here:<br />
+ <html:text property="filePath" /><br /><br />
<html:submit />