Date: 2005-03-02T11:40:38 Editor: DakotaJack Wiki: Apache Struts Wiki Page: StrutsUpload URL: http://wiki.apache.org/struts/StrutsUpload
no comment Change Log: ------------------------------------------------------------------------------ @@ -1,151 +1,33 @@ -##language:en == Introduction == -I have tried to discuss ways to make life easy for everyone in the Struts upload area, i.e. for the default application and for alternative applications. As things stand, the default application is fairly wedded deep into the framework itself, which, I think, is unnecessary and which, I think, stifles chances to explore other options. There is nothing wrong, of course, with the Struts upload application and this is not a criticism. I would, myself, like to be able to use the !ActionForm with a more "detailed" or more "sophisticated" application. If we can get by that hurdle, I would be happy to donate the code to Struts, if anyone wants it. Getting by that hurdle is not made easier by my apparent difficulties communicating what I am trying to do to the committers. They seem to think I am asking someone else to do something. I am not. Anyway, if anyone has time to read all the following, that would be best. If someone does not have the time, let me say that I am beginning by suggesting a different approach to the present !MultipartRequestHandler and !MultipartRequestWrapper, as well as to where wrapper and handler classes are introduced into the framework. I have tried to build a wrapper (facade) and a handler which will be agnostic towards any particular solutions, unlike the present wrapper and handler. The wrapper/facade is not sufficient to pass to the Action as the request. It is not even a wrapper in that sense. Nor, I think, would that be desireable. However, if one wants to do that, I will provide a true wrapper connected to the code by implementing the facade methods in a wrapper in addition to the regular !HttpServletRequest and !ServletRequest methods. On to the code, then. Any questions would be welcome: [EMAIL PROTECTED] +This wiki page is an attempt to open some serious dialogue on providing a multipart request API in the Struts framework that will work for the default Struts upload application as well as alternative implementations and applications. Presently alternative implementations have to forego using ActionForm because the populate method of RequestUtils necessitates using the default MultipartRequestWrapper and the default MultipartRequestHandler. -== Struts Multipart Processing in Struts v1.2.6 for Upload Applications == +I have suggested using an alternative MultipartRequestHandler which will promote alternative ideas and have supplanted the MultipartRequestWrapper with a MultipartData interface. If the committers want to continue passing the MultipartRequestWrapper to the Action, then this can be accomplished by passing the implementation of the MultipartData interface to the MultipartRequestWrapper. -The present code in Struts v1.2.6 and before is tied to the "default" or "existing" upload application supplied in the Struts jar file. By "tied" I mean that the code is coupled to that application such that it unnecessarily impedes the development of competing or alternative implementations. This is not a criticism of the default application. Rather, it is a desire to decouple a particular implementation which is not a very sophisticated upload application, from the framework. This is not a hard thing to do, and hopefully this wiki page will start a discussion of how that might be achieved, if desireable. As things stand, people regularly have to build around the multipart processing in Struts rather than benefit from it. What is proposed here hopefully would provide a basis for keeping what is good about the present application while allowing other alternatives to be used too. +I would strongly suggest, however, not wrapping the multipart request and getting the appropriate multipart data from the ActionForm alone. -The changes suggested here can easily be implemented as is. I am going to, however, first present the ideas and then see if anyone is interested in going further. +Below you will find suggested alternatives to the existing wrapper and handler. The suggestion is to provide two Globals fields to identify the MultipartData and MultipartRequestHandler which would be set in the mapping for whatever UploadAction subclass of Action is implemented. -I am going to suggest changes in multipart processing in Struts v1.2.6 and forward. Equivalent changes are suggested for the chain implementations of !RequestProcessor. +The point of all this is shown in the implementation of the MultipartRequestHandler below. As you can see, this alternative, while costing nothing, allows us to make our applications as sophisticated as we want by varying the input parameters to the handleRequest(Object []) method of the MultipartRequestHandler. In our example, we (1) pass in information with "maxFileSize" and "repositoryPath" to tell the handler what to do; (2) pass in Maps "parameterNames" and "files" as well as the "encoding" paramenter to be initialized by the handler; (3) pass in a List of monitors to be embedded in wrappers of the commons file upload package FileItem, DiskFileUpload, etc. -Let's first see that the present state of v1.2.6 is. Multipart processing in Struts v1.2.6 is fairly simple even if a bit "discombobbled". The relevant classes are: +== Suggested Code == - 1. Globals - 2. !ActionForm - 3. !RequestProcessor - 4. !IncludeAction - 5. !ActionConfig - 6. !ConfigHelper - 7. !ConfigHelperInterface - 8. !ControllerConfig - 9. !RequestUtils - -Let's follow the bouncing-ball like in the old time silent movie sing-alongs. The first thing to happen in the process method of !RequestProcessor in Struts v1.2.6 is the wrapping of the request, if relevant, in a !MultipartRequestWrapper with: - -=== RequestProcessor === - -{{{ -request = processMultipart(request); -}}} - -This is a pretty simple operation/method. - -{{{ -protected HttpServletRequest processMultipart(HttpServletRequest request) { - if (!"POST".equalsIgnoreCase(request.getMethod())) { - return (request); - } - - String contentType = request.getContentType(); - if ((contentType != null) && - contentType.startsWith("multipart/form-data")) { - return (new MultipartRequestWrapper(request)); - } else { - return (request); - } -} -}}} - -The reason for wrapping the request at this point is not clear, or even a mistake. The resultant !MultipartRequestWrapper is not initialized, i.e. the state is not set. However, in some places, because Struts v1.2.6 is Servlet 2.2 compatible, the wrapper must be unwrapped, e.g. where the request must be accessed for forwards and includes, cf. doForward(...) and doInclude(...) in !RequestProcessor. - -If the multipart request wrapper did not implement the !HttpServletRequest, none of these difficulties with the differences between Servlet v2.2 and v2.3 would exist. I will suggest an alternative to avoid this. There is a wise preference of composition to inheritance in coding generally, but in this case we do not even need composition, much less inheritance. This will be revisited below. - -This is just extra coding with no value. In !ConfigHelper this leads somehow to the !MultipartRequestWrapper and the !MultiparRequestHandler in Struts v1.2.6 getting confused. The following code is in !ConfigHelper: - -{{{ -public MultipartRequestWrapper getMultipartRequestWrapper() { - if (this.request == null) { - return null; - } - return (MultipartRequestWrapper) this.request.getAttribute(Globals.MULTIPART_KEY); -} -}}} - - -However, the class which is persisted under Globals.MULTIPART_KEY is the !MultipartRequestHandler and not the !MultipartRequestWrapper. This code can be, and I understand will be, jettisoned entirely. - -Let's look briefly at the !MultipartRequestWrapper in the upload application, which here has insinuated itself into the Struts framework code unnecessarily. - -==== EXISTING MultipartRequestWrapper ==== +=== MultipartRequestHandler === {{{ -public class MultipartRequestWrapper implements HttpServletRequest { - protected Map parameters; - protected HttpServletRequest request; - - public MultipartRequestWrapper(HttpServletRequest request) { - this.request = request; - this.parameters = new HashMap(); - } - - public void setParameter(String name, String value) { - String[] mValue = (String[]) parameters.get(name); - if (mValue == null) { - mValue = new String[0]; - } - String[] newValue = new String[mValue.length + 1]; - System.arraycopy(mValue, 0, newValue, 0, mValue.length); - newValue[mValue.length] = value; - - parameters.put(name, newValue); - } - - public String getParameter(String name) { - String value = request.getParameter(name); - if (value == null) { - String[] mValue = (String[]) parameters.get(name); - if ((mValue != null) && (mValue.length > 0)) { - value = mValue[0]; - } - } - return value; - } - - public Enumeration getParameterNames() { - Enumeration baseParams = request.getParameterNames(); - Vector list = new Vector(); - while (baseParams.hasMoreElements()) { - list.add(baseParams.nextElement()); - } - Collection multipartParams = parameters.keySet(); - Iterator iterator = multipartParams.iterator(); - while (iterator.hasNext()) { - list.add(iterator.next()); - } - return Collections.enumeration(list); - } - - public String[] getParameterValues(String name) { - String[] value = request.getParameterValues(name); - if (value == null) { - value = (String[]) parameters.get(name); - } - return value; - } - - public HttpServletRequest getRequest() { - return request; - } - - //WRAPPER IMPLEMENTATIONS OF SERVLET REQUEST METHODS - ..... - //WRAPPER IMPLEMENTATIONS OF HTTPSERVLETREQUEST METHODS - ..... - //SERVLET 2.3 EMPTY METHODS - ..... +public interface MultipartRequestHandler { + public void handleRequest(Object [] params) throws IOException; + public void setServlet(ActionServlet servlet); + public void setMapping(ActionMapping mapping); + public ActionServlet getServlet(); + public ActionMapping getMapping(); } - }}} -We will see that can do the same thing, and more, with the far less intrusive and hugely more flexible. I add "Upload" to the class names in the following for purposes of ease of discussion. (I realize that we might need a real wrapper for a request object, so I call the following code a "facade", which it is. However, if a real wrapper is needed, to pass to the Action, which I don't think is a good idea, actually, then we can do so by including this class in that wrapper to get the values of the methods in our facade. - -==== SUGGESTED UploadMultipartFacade ==== +=== MultipartData === {{{ -public interface UploadMultipartFacade { +public interface MultipartData { public Iterator getParameterNames(); public String getParameter(String name); public String[] getParameterValues(String name); @@ -153,146 +35,43 @@ } }}} -In addition to the flexibility, etc. of this interface, it also gives us what we wanted from such wrapper: the files! But, let's continue down the request processing chain in Struts v1.2.6. - -The next relevant code is in the processPopulate(...) method of !RequestProcessor. Early on in processPopulate(...) we find the value of Globals.MULTIPART_KEY being set. There is no need to do this so early, which just restricts options, and the reason might be that there is confusion about which class is covered by the key. At any rate, shortly thereafter !RequestUtils' method populate(...) is called, and this is the first relevant code. This is where, unfortunately, I think, the !ActionForm gets unnecessarily wedded to the !MultipartRequestWrapper and !MultipartRequestHandler. The populate method has as parameters !ActionForm, String (mapping.getPrefix()), String (mapping getSuffix()), and !HttpServletRequest (which has been cast to !MultipartRequestWrapper but no state has been set in !MultipartRequestWrapper, so that is irrelevant. The code is just what I call a "cuffudgal", which means generally that there is no particular rhyme or reason to where the code is placed. This is not meant as a criticism of anyone, but only of the code. Presumably code can be criticized without being uncivil? - -=== RequestUtils === - -with the !RequestUtils populate(...) method, the Struts v1.2.6 upload application !MultipartRequestHandler enters the picture. The populate method is: +=== MultipartUtil === {{{ -public static void populate( - Object bean, - String prefix, - String suffix, - HttpServletRequest request) - throws ServletException { - HashMap properties = new HashMap(); - Enumeration names = null; - Map multipartParameters = null; - - String contentType = request.getContentType(); - String method = request.getMethod(); - boolean isMultipart = false; - - if ((contentType != null) - && (contentType.startsWith("multipart/form-data")) - && (method.equalsIgnoreCase("POST"))) { - ActionServletWrapper servlet; - if (bean instanceof ActionForm) { - servlet = ((ActionForm) bean).getServletWrapper(); - } else { - throw new ServletException("bean that's supposed to be " - + "populated from a multipart request is not of type " - + "\"org.apache.struts.action.ActionForm\", but type " - + "\"" - + bean.getClass().getName() - + "\""); - } - MultipartRequestHandler multipartHandler = getMultipartHandler(request); - (ActionForm) bean).setMultipartRequestHandler(multipartHandler); - if (multipartHandler != null) { - isMultipart = true; - servlet.setServletFor(multipartHandler); - multipartHandler.setMapping( - (ActionMapping) request.getAttribute(Globals.MAPPING_KEY)); - multipartHandler.handleRequest(request); - Boolean maxLengthExceeded = - (Boolean) request.getAttribute( - MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED); - if ((maxLengthExceeded != null) && (maxLengthExceeded.booleanValue())) { - return; - } - multipartParameters = getAllParametersForMultipartRequest( - request, multipartHandler); - names = Collections.enumeration(multipartParameters.keySet()); +public class MultipartUtil { + public static final String MULTIPART_FORM_DATA = "multipart/form-data"; + public static final String CONTENT_TYPE = "Content-Type"; + + public static boolean isMultipartFormData(HttpServletRequest req) { + String contentType = null; + String headerContentType = req.getHeader(CONTENT_TYPE); + String requestContentType = req.getContentType(); + + if(headerContentType == null && requestContentType != null) { + contentType = requestContentType; + } else if(requestContentType == null && headerContentType != null) { + contentType = headerContentType; + } else if(headerContentType != null && requestContentType != null) { + contentType = headerContentType.length() <= requestContentType.length() ? requestContentType : headerContentType; } - } - - if (!isMultipart) { - names = request.getParameterNames(); - } - - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - String stripped = name; - if (prefix != null) { - if (!stripped.startsWith(prefix)) { - continue; - } - stripped = stripped.substring(prefix.length()); - } - if (suffix != null) { - if (!stripped.endsWith(suffix)) { - continue; - } - stripped = stripped.substring(0, stripped.length() - suffix.length()); - } - Object parameterValue = null; - if (isMultipart) { - parameterValue = multipartParameters.get(name); - } else { - parameterValue = request.getParameterValues(name); - } - if (!(stripped.startsWith("org.apache.struts."))) { - properties.put(stripped, parameterValue); - } - } - try { - BeanUtils.populate(bean, properties); - } catch(Exception e) { - throw new ServletException("BeanUtils.populate", e); + return contentType != null && contentType.toLowerCase().startsWith(MULTIPART_FORM_DATA); } } }}} - -The multipart request handler has the following code: - -==== EXISTING MultipartRequestHandler ==== - -{{{ -public interface MultipartRequestHandler { - public static final String ATTRIBUTE_MAX_LENGTH_EXCEEDED = "org.apache.struts.upload.MaxLengthExceeded"; - public void setServlet(ActionServlet servlet); - public void setMapping(ActionMapping mapping); - public ActionServlet getServlet(); - public ActionMapping getMapping(); - public void handleRequest(HttpServletRequest request) throws ServletException; - public Hashtable getTextElements(); - public Hashtable getFileElements(); -} -}}} - -With due respect and deference to whomever coded this handler, it does way too much. What we need is a request handler that will handle the request and get what the multipart request wrapper needs to do its work. All the rest just ties the class down in the middle of the framework. These details should be in the application, if wanted, but not in the framework. I would suggest, rather, the following interface: - -==== SUGGESTED UploadMultipartRequestHandler ==== +=== UploadMultipartData === {{{ -public interface UploadMultipartRequestHandler { - public void handleRequest(Object [] params) throws IOException; -} -}}} - -The only params that the handleRequest(...) method "must" take are two maps: one for parameter names and one for files in the !UploadMultipartFacade. The interface as defined allows one to create whatever other decorating params as one desires. I do the following in my coding, which puts the maximum file size, encoding, and repository/store path into the mix and initializes a list of monitors/listeners as well as the maps of parameter names and files needed by the !UploadMultipartFacade: - -First the !UploadMultipartFacadeImpl and then the !MultipartRequestHandlerImpl: - -==== SUGGESTED UploadMultipartFacadeImpl ==== - -{{{ - -public class UploadMultipartFacadeImpl - implements UploadMultipartFacade { +public class UploadMultipartData + implements MultipartData { private Map parameterNames; private Map files; - public UploadMultipartFacadeImpl(HttpServletRequest req, - List monitors, - int fileSizeLimit, - String encoding) + public UploadMultipartData(HttpServletRequest req, + List monitors, + int fileSizeLimit, + String encoding) throws UploadException, IOException { @@ -303,11 +82,15 @@ parameterNames = Collections.synchronizedMap(new HashMap(89)); files = Collections.synchronizedMap(new HashMap(89)); - UploadMultipartRequestHandler umrh = new UploadMultipartRequestHandlerImpl(); - - Object [] objects = new Object [] { req,monitors, new Integer(fileSizeLimit),parameterNames,files, UploadConstant.PARSER_TEMP_DIR, encoding }; + MultipartRequestHandler handler = new UploadMultipartRequestHandler(); - umrh.handleRequest(objects); + Object [] objects = new Object [] { req,monitors, + new Integer(fileSizeLimit), + parameterNames, + files, + UploadConstant.PARSER_TEMP_DIR, + encoding }; + handler.handleRequest(objects); } public Iterator getParameterNames() { @@ -338,14 +121,15 @@ } }}} -==== SUGGESTED UploadMultipartRequestHandlerImpl ==== +=== UploadMultipartRequestHandler === {{{ +public class UploadMultipartRequestHandler + implements MultipartRequestHandler { + private ActionMapping mapping; + private ActionServlet servlet; -public class UploadMultipartRequestHandlerImpl - implements UploadMultipartRequestHandler { - - public UploadMultipartRequestHandlerImpl() { + public UploadMultipartRequestHandler() { } public void handleRequest(Object [] params) @@ -372,21 +156,21 @@ ufiFactory.setMonitors(monitors); ufiFactory.setCustom(req.getContentLength()); - DiskFileUpload cdfu = new DiskFileUpload(); + DiskFileUpload dfu = new DiskFileUpload(); - cdfu.setFileItemFactory(ufiFactory); - cdfu.setSizeMax(maxFileSize); - cdfu.setSizeThreshold(UploadConstant.BUFFER_SIZE); - cdfu.setRepositoryPath(repositoryPath); + dfu.setFileItemFactory(ufiFactory); + dfu.setSizeMax(maxFileSize); + dfu.setSizeThreshold(UploadConstant.BUFFER_SIZE); + dfu.setRepositoryPath(repositoryPath); if(encoding != null) { - cdfu.setHeaderEncoding(encoding); + dfu.setHeaderEncoding(encoding); } List list = null; try { - list = cdfu.parseRequest(req); + list = dfu.parseRequest(req); } catch(FileUploadException cfue) { throw new IOException(cfue.getMessage()); } @@ -394,15 +178,15 @@ Object obj = null; for(Iterator iterator = list.iterator(); iterator.hasNext();) { - FileItem cfi = (FileItem)iterator.next(); - String fieldName = cfi.getFieldName(); + FileItem fi = (FileItem)iterator.next(); + String fieldName = fi.getFieldName(); - if(cfi.isFormField()) { + if(fi.isFormField()) { String data = null; if(encoding != null) { - data = cfi.getString(encoding); + data = fi.getString(encoding); } else { - data = cfi.getString(); + data = fi.getString(); } List names = (List)parameterNames.get(fieldName); @@ -414,9 +198,9 @@ names.add(data); } else { - String name = cfi.getName(); + String name = fi.getName(); if(name != null) { - UploadFile fuuf = new UploadFileImpl(cfi); + FormFile uf = new UploadFormFile(fi); name = name.replace('\\', '/'); int j = name.lastIndexOf("/"); @@ -424,302 +208,82 @@ name = name.substring(j + 1, name.length()); } - fuuf.setFileName(name); - fuuf.setContentType(cfi.getContentType()); - fuuf.setFileSize(cfi.getSize()); - files.put(fieldName, fuuf); + uf.setFileName(name); + uf.setFileContentType(fi.getContentType()); + uf.setFileSize(fi.getSize()); + files.put(fieldName, uf); } } } } -} - -}}} - -Essentially, this way of coding the internals of the framework to service potential upload applications maximizes the potential for alternative implementations, etc. - -I think this is a good place to stop, and to see if discussions are possible on this. I have built and entire application, utilizing wrappers around commons fileupload classes, with the multipart facade and multipart request handler classes in my upload directory which can be discussed further, if there is any interest. - -My eyes are going buggy from reading this, so I will do a lot of the cleanup of typos later. Any notes on those or anything else would be appreciated. - -Jack - ------- - -The implementation of the !MultimpartRequestHandler in Strust upload is: -{{{ -public class CommonsMultipartRequestHandler implements MultipartRequestHandler { - public static final long DEFAULT_SIZE_MAX = 250 * 1024 * 1024; - public static final int DEFAULT_SIZE_THRESHOLD = 256 * 1024; - protected static Log log = LogFactory.getLog( - CommonsMultipartRequestHandler.class); - private Hashtable elementsAll; - private Hashtable elementsFile; - private Hashtable elementsText; - private ActionMapping mapping; - private ActionServlet servlet; - public ActionServlet getServlet() { return this.servlet; } - + public void setServlet(ActionServlet servlet) { this.servlet = servlet; } - + public ActionMapping getMapping() { return this.mapping; } - + public void setMapping(ActionMapping mapping) { this.mapping = mapping; } - - public void handleRequest(HttpServletRequest request) - throws ServletException { - ModuleConfig ac = (ModuleConfig) request.getAttribute( - Globals.MODULE_KEY); - DiskFileUpload upload = new DiskFileUpload(); - upload.setHeaderEncoding(request.getCharacterEncoding()); - upload.setSizeMax(getSizeMax(ac)); - upload.setSizeThreshold((int) getSizeThreshold(ac)); - upload.setRepositoryPath(getRepositoryPath(ac)); - elementsText = new Hashtable(); - elementsFile = new Hashtable(); - elementsAll = new Hashtable(); - +} +}}} - List items = null; - try { - items = upload.parseRequest(request); - } catch (DiskFileUpload.SizeLimitExceededException e) { - request.setAttribute( - MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED, - Boolean.TRUE); - return; - } catch (FileUploadException e) { - log.error("Failed to parse multipart request", e); - throw new ServletException(e); - } - - Iterator iter = items.iterator(); - while (iter.hasNext()) { - FileItem item = (FileItem) iter.next(); - if (item.isFormField()) { - addTextParameter(request, item); - } else { - addFileParameter(item); - } - } - } - - public Hashtable getTextElements() { - return this.elementsText; - } - - public Hashtable getFileElements() { - return this.elementsFile; - } - - public Hashtable getAllElements() { - return this.elementsAll; - } - - public void rollback() { - Iterator iter = elementsFile.values().iterator(); +=== FormFile === - while (iter.hasNext()) { - FormFile formFile = (FormFile) iter.next(); +{{{ +public abstract class FormFile + implements Serializable { + private String fileContentType; + private String fileName; + private long fileSize; - formFile.destroy(); - } - } - - public void finish() { - rollback(); - } - - protected long getSizeMax(ModuleConfig mc) { - return convertSizeToBytes( - mc.getControllerConfig().getMaxFileSize(), - DEFAULT_SIZE_MAX); - } - - protected long getSizeThreshold(ModuleConfig mc) { - return convertSizeToBytes( - mc.getControllerConfig().getMemFileSize(), - DEFAULT_SIZE_THRESHOLD); - } - - protected long convertSizeToBytes(String sizeString, long defaultSize) { - int multiplier = 1; - - if (sizeString.endsWith("K")) { - multiplier = 1024; - } else if (sizeString.endsWith("M")) { - multiplier = 1024 * 1024; - } else if (sizeString.endsWith("G")) { - multiplier = 1024 * 1024 * 1024; - } - if (multiplier != 1) { - sizeString = sizeString.substring(0, sizeString.length() - 1); - } - - long size = 0; - try { - size = Long.parseLong(sizeString); - } catch (NumberFormatException nfe) { - log.warn("Invalid format for file size ('" + sizeString + - "'). Using default."); - size = defaultSize; - multiplier = 1; - } - - return (size * multiplier); + public FormFile(String fileName, + String fileContentType, + long fileSize) { + this.fileSize = -1L; + this.fileName = fileName; + this.fileContentType = fileContentType; + this.fileSize = fileSize; } - - protected String getRepositoryPath(ModuleConfig mc) { - - // First, look for an explicitly defined temp dir. - String tempDir = mc.getControllerConfig().getTempDir(); - - // If none, look for a container specified temp dir. - if (tempDir == null || tempDir.length() == 0) { - if (servlet != null) { - ServletContext context = servlet.getServletContext(); - File tempDirFile = (File) context.getAttribute( - "javax.servlet.context.tempdir"); - tempDir = tempDirFile.getAbsolutePath(); - } - - // If none, pick up the system temp dir. - if (tempDir == null || tempDir.length() == 0) { - tempDir = System.getProperty("java.io.tmpdir"); - } - } - if (log.isTraceEnabled()) { - log.trace("File upload temp dir: " + tempDir); - } + public FormFile() { + this(null, null, -1L); + } - return tempDir; + public long getFileSize() { + return fileSize; } - - protected void addTextParameter(HttpServletRequest request, FileItem item) { - String name = item.getFieldName(); - String value = null; - boolean haveValue = false; - String encoding = request.getCharacterEncoding(); - - if (encoding != null) { - try { - value = item.getString(encoding); - haveValue = true; - } catch (Exception e) { - // Handled below, since haveValue is false. - } - } - if (!haveValue) { - try { - value = item.getString("ISO-8859-1"); - } catch (java.io.UnsupportedEncodingException uee) { - value = item.getString(); - } - haveValue = true; - } - if (request instanceof MultipartRequestWrapper) { - MultipartRequestWrapper wrapper = (MultipartRequestWrapper) request; - wrapper.setParameter(name, value); - } + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } - String[] oldArray = (String[]) elementsText.get(name); - String[] newArray; + public String getFileName() { + return fileName; + } - if (oldArray != null) { - newArray = new String[oldArray.length + 1]; - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); - newArray[oldArray.length] = value; - } else { - newArray = new String[] { value }; - } + public void setFileName(String fileName) { + this.fileName = fileName; + } - elementsText.put(name, newArray); - elementsAll.put(name, newArray); + public String getFileContentType() { + return fileContentType; } - - protected void addFileParameter(FileItem item) { - FormFile formFile = new CommonsFormFile(item); - - elementsFile.put(item.getFieldName(), formFile); - elementsAll.put(item.getFieldName(), formFile); - } - - static class CommonsFormFile implements FormFile, Serializable { - FileItem fileItem;public CommonsFormFile(FileItem fileItem) { - this.fileItem = fileItem; - } - - public String getContentType() { - return fileItem.getContentType(); - } - - public void setContentType(String contentType) { - throw new UnsupportedOperationException( - "The setContentType() method is not supported."); - } - - public int getFileSize() { - return (int)fileItem.getSize(); - } - - public void setFileSize(int filesize) { - throw new UnsupportedOperationException( - "The setFileSize() method is not supported."); - } - - public String getFileName() { - return getBaseFileName(fileItem.getName()); - } - - public void setFileName(String fileName) { - throw new UnsupportedOperationException( - "The setFileName() method is not supported."); - } - - public byte[] getFileData() throws FileNotFoundException, IOException { - return fileItem.get(); - } - - public InputStream getInputStream() throws FileNotFoundException, IOException { - return fileItem.getInputStream(); - } - - public void destroy() { - fileItem.delete(); - } - - protected String getBaseFileName(String filePath) { - String fileName = new File(filePath).getName(); - int colonIndex = fileName.indexOf(":"); - if (colonIndex == -1) { - colonIndex = fileName.indexOf("\\\\"); - } - int backslashIndex = fileName.lastIndexOf("\\"); - if (colonIndex > -1 && backslashIndex > -1) { - fileName = fileName.substring(backslashIndex + 1); - } - return fileName; - } - - public String toString() { - return getFileName(); - } + public void setFileContentType(String fileContentType) { + this.fileContentType = fileContentType; } + + public abstract byte[] getFileData(); + public abstract InputStream getFileInputStream(); + public abstract void reset(); } }}} - ------ --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]