1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dbforms.util;
25
26 import org.apache.commons.fileupload.DiskFileUpload;
27 import org.apache.commons.fileupload.FileItem;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.io.InputStream;
34
35 import java.util.Enumeration;
36 import java.util.Hashtable;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Vector;
40
41 import javax.servlet.http.HttpServletRequest;
42 import org.dbforms.util.external.FileUtil;
43
44
45 /***
46 * A utility class to handle <code>multipart/form-data</code> requests, the
47 * kind of requests that support file uploads. This class emulates the interface
48 * of <code>HttpServletRequest</code>, making it familiar to use. It uses a
49 * "push" model where any incoming files are read and saved directly to disk in
50 * the constructor. If you wish to have more flexibility, e.g. write the files
51 * to a database, use the "pull" model <code>MultipartParser</code> instead.
52 * <p>
53 * This class can receive arbitrarily large files (up to an artificial limit you
54 * can set), and fairly efficiently too. It cannot handle nested data (multipart
55 * content within multipart content) or internationalized content (such as non
56 * Latin-1 filenames).
57 * </p>
58 * <p>
59 * See the included <a href="upload.war">upload.war </a> for an example of how
60 * to use this class.
61 * <p>
62 * The full file upload specification is contained in experimental RFC 1867,
63 * available at <a href="http://www.ietf.org/rfc/rfc1867.txt"
64 * http://www.ietf.org/rfc/rfc1867.txt </a>.
65 * </p>
66 * <p>
67 * PLEASE NOTE: this class uses Multipart Support Classes by Jason Hunter.
68 * Copyright (C) 1998 by Jason Hunter. All rights reserved.
69 * Use of this class is limited. Please see the LICENSE for more information.
70 * Make sure that you project meets the requierements defined by Jason Hunter
71 * respective O'reilly!
72 * </p>
73 *
74 * @see MultipartParser
75 *
76 * @author Jason Hunter
77 * @author Geoff Soutter
78 * @author Joe Peer - _changed_ it for use in DbForms (i apologize)
79 */
80 public class MultipartRequest {
81 private static Log logCat = LogFactory.getLog(MultipartRequest.class);
82 private Hashtable files = new Hashtable();
83
84
85
86 private Hashtable parameters = new Hashtable();
87
88 private String fileName2SystemFileName(String filename) {
89 String filenm = "";
90 if ('/' != File.separatorChar) {
91 filenm = filename.replace('/', File.separatorChar);
92 }
93 if ('//' != File.separatorChar) {
94 filenm = filename.replace('//', File.separatorChar);
95 }
96 return filenm;
97 }
98
99
100 /***
101 * Constructs a new MultipartRequest to handle the specified request,
102 * {saving any uploaded files to the given directory}, and limiting the
103 * upload size to the specified length. If the content is too large, an
104 * IOException is thrown. This constructor actually parses the
105 * <tt>multipart/form-data</tt> and throws an IOException if there's any
106 * problem reading or parsing the request.
107 *
108 * @param request
109 * the servlet request.
110 * @param maxPostSize
111 * the maximum size of the POST content.
112 * @exception IOException
113 * if the uploaded content is larger than
114 * <tt>maxPostSize</tt> or there's a problem reading or
115 * parsing the request.
116 */
117 public MultipartRequest(HttpServletRequest request,
118 int maxPostSize)
119 throws IOException {
120
121 if (request == null) {
122 throw new IllegalArgumentException("request cannot be null");
123 }
124
125
126 DiskFileUpload upload = new DiskFileUpload();
127
128
129 upload.setSizeMax(maxPostSize);
130
131 String tmpDir = System.getProperty("java.io.tmpdir");
132 upload.setRepositoryPath(tmpDir);
133
134
135 try {
136 List items = upload.parseRequest(request);
137 Iterator iter = items.iterator();
138
139 while (iter.hasNext()) {
140 FileItem item = (FileItem) iter.next();
141 String name = item.getFieldName();
142
143 if (item.isFormField()) {
144 String value = item.getString();
145
146
147 Vector existingValues = (Vector) parameters.get(name);
148
149 if (existingValues == null) {
150 existingValues = new Vector();
151 parameters.put(name, existingValues);
152 }
153
154 existingValues.addElement(value);
155 } else {
156 String fileName = item.getName();
157
158 if (!Util.isNull(fileName)) {
159
160
161 fileName = FileUtil.filename(fileName2SystemFileName(fileName));
162
163
164
165
166
167
168 FileHolder fileHolder = new FileHolder(fileName, item);
169 files.put(name, fileHolder);
170 logCat.info("buffered and now added as " + name
171 + " the following fileHolder:"
172 + fileHolder.getFileName());
173
174
175
176
177
178
179
180 Vector existingValues = (Vector) parameters.get(name);
181
182 if (existingValues == null) {
183 existingValues = new Vector();
184 parameters.put(name, existingValues);
185 }
186
187 existingValues.addElement(fileName);
188 }
189 }
190 }
191 } catch (Exception e) {
192 logCat.error("MultipartRequest", e);
193 }
194 }
195
196 /***
197 * Returns the content type of the specified file (as supplied by the client
198 * browser), or null if the file was not included in the upload.
199 *
200 * @param name
201 * the file name.
202 * @return the content type of the file.
203 */
204 public String getContentType(String name) {
205 try {
206
207
208 FileHolder filePart = (FileHolder) files.get(name);
209
210 return filePart.getContentType();
211 } catch (Exception e) {
212 return null;
213 }
214 }
215
216
217 /***
218 * Returns a FilePart object for the specified file this method was added by
219 * joe peer
220 *
221 * @param name
222 * the file name.
223 * @return a FilePart object for the named file.
224 */
225 public FileHolder getFileHolder(String name) {
226 try {
227 return (FileHolder) files.get(name);
228 } catch (Exception e) {
229 return null;
230 }
231 }
232
233
234 /***
235 * Returns a InputStream object for the specified file saved on the server's
236 * filesystem, or null if the file was not included in the upload.
237 *
238 * @param name
239 * the file name.
240 * @return a InputStream object for the named file.
241 */
242 public InputStream getFileInputStream(String name) {
243 try {
244
245
246 FileHolder filePart = (FileHolder) files.get(name);
247
248 return filePart.getInputStreamFromBuffer();
249 } catch (Exception e) {
250 return null;
251 }
252 }
253
254
255 /***
256 * Returns the names of all the uploaded files as an Enumeration of Strings.
257 * It returns an empty Enumeration if there are no uploaded files. Each file
258 * name is the name specified by the form, not by the user.
259 *
260 * @return the names of all the uploaded files as an Enumeration of Strings.
261 */
262 public Enumeration getFileNames() {
263 return files.keys();
264 }
265
266
267 /***
268 * Returns the filesystem name of the specified file, or null if the file
269 * was not included in the upload. A filesystem name is the name specified
270 * by the user. It is also the name under which the file is actually saved.
271 *
272 * @param name
273 * the file name.
274 * @return the filesystem name of the file.
275 */
276 public String getFilesystemName(String name) {
277 try {
278
279
280 FileHolder filePart = (FileHolder) files.get(name);
281
282 return filePart.getFileName();
283 } catch (Exception e) {
284 return null;
285 }
286 }
287
288
289 /***
290 * Returns the value of the named parameter as a String, or null if the
291 * parameter was not sent or was sent without a value. The value is
292 * guaranteed to be in its normal, decoded form. If the parameter has
293 * multiple values, only the last one is returned (for backward
294 * compatibility). For parameters with multiple values, it's possible the
295 * last "value" may be null.
296 *
297 * @param name
298 * the parameter name.
299 * @return the parameter value.
300 */
301 public String getParameter(String name) {
302 try {
303 Vector values = (Vector) parameters.get(name);
304
305 if ((values == null) || (values.size() == 0)) {
306 return null;
307 }
308
309 String value = (String) values.elementAt(0);
310
311 return value;
312 } catch (Exception e) {
313 return null;
314 }
315 }
316
317
318 /***
319 * Returns the names of all the parameters as an Enumeration of Strings. It
320 * returns an empty Enumeration if there are no parameters.
321 *
322 * @return the names of all the parameters as an Enumeration of Strings.
323 */
324 public Enumeration getParameterNames() {
325 return parameters.keys();
326 }
327
328
329 /***
330 * Returns the values of the named parameter as a String array, or null if
331 * the parameter was not sent. The array has one entry for each parameter
332 * field sent. If any field was sent without a value that entry is stored in
333 * the array as a null. The values are guaranteed to be in their normal,
334 * decoded form. A single value is returned as a one-element array.
335 *
336 * @param name
337 * the parameter name.
338 * @return the parameter values.
339 */
340 public String[] getParameterValues(String name) {
341 try {
342 Vector values = (Vector) parameters.get(name);
343
344 if ((values == null) || (values.size() == 0)) {
345 return null;
346 }
347
348 String[] valuesArray = new String[values.size()];
349 values.copyInto(valuesArray);
350
351 return valuesArray;
352 } catch (Exception e) {
353 return null;
354 }
355 }
356 }