Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/MultiPartInputStream.java @ 859:3dcc52e17535
simplify multipart
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 21 Sep 2016 16:15:19 -0600 |
parents | 7fb7c1915788 |
children |
comparison
equal
deleted
inserted
replaced
858:dbbd9c3f14f8 | 859:3dcc52e17535 |
---|---|
41 import java.util.Locale; | 41 import java.util.Locale; |
42 import java.util.Map; | 42 import java.util.Map; |
43 import java.util.StringTokenizer; | 43 import java.util.StringTokenizer; |
44 import java.util.Base64; | 44 import java.util.Base64; |
45 | 45 |
46 import javax.servlet.MultipartConfigElement; | |
47 import javax.servlet.ServletException; | 46 import javax.servlet.ServletException; |
48 import javax.servlet.http.Part; | 47 import javax.servlet.http.Part; |
49 | 48 |
50 import org.slf4j.Logger; | 49 import org.slf4j.Logger; |
51 import org.slf4j.LoggerFactory; | 50 import org.slf4j.LoggerFactory; |
59 */ | 58 */ |
60 public class MultiPartInputStream | 59 public class MultiPartInputStream |
61 { | 60 { |
62 private static final Logger LOG = LoggerFactory.getLogger(MultiPartInputStream.class); | 61 private static final Logger LOG = LoggerFactory.getLogger(MultiPartInputStream.class); |
63 | 62 |
64 public static final MultipartConfigElement __DEFAULT_MULTIPART_CONFIG = new MultipartConfigElement(System.getProperty("java.io.tmpdir")); | |
65 protected InputStream _in; | 63 protected InputStream _in; |
66 protected MultipartConfigElement _config; | |
67 protected String _contentType; | 64 protected String _contentType; |
68 protected MultiMap<String> _parts; | 65 protected MultiMap<String> _parts; |
69 protected File _tmpDir; | 66 |
70 protected File _contextTmpDir; | 67 |
71 protected boolean _deleteOnExit; | 68 |
72 | 69 public final class MultiPart implements Part |
73 | |
74 | |
75 public class MultiPart implements Part | |
76 { | 70 { |
77 protected String _name; | 71 protected String _name; |
78 protected String _filename; | 72 protected String _filename; |
79 protected File _file; | 73 protected File _file; |
80 protected OutputStream _out; | 74 protected OutputStream _out; |
81 protected ByteArrayOutputStream2 _bout; | 75 protected ByteArrayOutputStream2 _bout; |
82 protected String _contentType; | 76 protected String _contentType; |
83 protected MultiMap<String> _headers; | 77 protected MultiMap<String> _headers; |
84 protected long _size = 0; | 78 protected long _size = 0; |
85 protected boolean _temporary = true; | |
86 | 79 |
87 public MultiPart (String name, String filename) | 80 public MultiPart (String name, String filename) |
88 throws IOException | 81 throws IOException |
89 { | 82 { |
90 _name = name; | 83 _name = name; |
123 | 116 |
124 | 117 |
125 protected void write (int b) | 118 protected void write (int b) |
126 throws IOException | 119 throws IOException |
127 { | 120 { |
128 if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartInputStream.this._config.getMaxFileSize()) | |
129 throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize"); | |
130 | |
131 if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + 1 > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null) | |
132 createFile(); | |
133 _out.write(b); | 121 _out.write(b); |
134 _size ++; | 122 _size ++; |
135 } | 123 } |
136 | 124 |
137 protected void write (byte[] bytes, int offset, int length) | 125 protected void write (byte[] bytes, int offset, int length) |
138 throws IOException | 126 throws IOException |
139 { | 127 { |
140 if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + length > MultiPartInputStream.this._config.getMaxFileSize()) | |
141 throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize"); | |
142 | |
143 if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + length > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null) | |
144 createFile(); | |
145 | |
146 _out.write(bytes, offset, length); | 128 _out.write(bytes, offset, length); |
147 _size += length; | 129 _size += length; |
148 } | 130 } |
149 | 131 |
150 protected void createFile () | 132 protected void createFile () |
151 throws IOException | 133 throws IOException |
152 { | 134 { |
153 _file = File.createTempFile("MultiPart", "", MultiPartInputStream.this._tmpDir); | 135 _file = File.createTempFile("MultiPart", null); |
154 if (_deleteOnExit) | 136 _file.deleteOnExit(); |
155 _file.deleteOnExit(); | |
156 FileOutputStream fos = new FileOutputStream(_file); | 137 FileOutputStream fos = new FileOutputStream(_file); |
157 BufferedOutputStream bos = new BufferedOutputStream(fos); | 138 BufferedOutputStream bos = new BufferedOutputStream(fos); |
158 | 139 |
159 if (_size > 0 && _out != null) | 140 if (_size > 0 && _out != null) |
160 { | 141 { |
251 /** | 232 /** |
252 * @see javax.servlet.http.Part#write(java.lang.String) | 233 * @see javax.servlet.http.Part#write(java.lang.String) |
253 */ | 234 */ |
254 public void write(String fileName) throws IOException | 235 public void write(String fileName) throws IOException |
255 { | 236 { |
256 if (_file == null) | 237 throw new UnsupportedOperationException(); |
257 { | |
258 _temporary = false; | |
259 | |
260 //part data is only in the ByteArrayOutputStream and never been written to disk | |
261 _file = new File (_tmpDir, fileName); | |
262 | |
263 BufferedOutputStream bos = null; | |
264 try | |
265 { | |
266 bos = new BufferedOutputStream(new FileOutputStream(_file)); | |
267 _bout.writeTo(bos); | |
268 bos.flush(); | |
269 } | |
270 finally | |
271 { | |
272 if (bos != null) | |
273 bos.close(); | |
274 _bout = null; | |
275 } | |
276 } | |
277 else | |
278 { | |
279 //the part data is already written to a temporary file, just rename it | |
280 _temporary = false; | |
281 | |
282 File f = new File(_tmpDir, fileName); | |
283 if (_file.renameTo(f)) | |
284 _file = f; | |
285 } | |
286 } | 238 } |
287 | 239 |
288 /** | 240 /** |
289 * Remove the file, whether or not Part.write() was called on it | 241 * Remove the file, whether or not Part.write() was called on it |
290 * (ie no longer temporary) | 242 * (ie no longer temporary) |
301 * | 253 * |
302 * @throws IOException | 254 * @throws IOException |
303 */ | 255 */ |
304 public void cleanUp() throws IOException | 256 public void cleanUp() throws IOException |
305 { | 257 { |
306 if (_temporary && _file != null && _file.exists()) | 258 if (_file != null && _file.exists()) |
307 _file.delete(); | 259 _file.delete(); |
308 } | 260 } |
309 | 261 |
310 | 262 |
311 /** | 263 /** |
335 * @param in Request input stream | 287 * @param in Request input stream |
336 * @param contentType Content-Type header | 288 * @param contentType Content-Type header |
337 * @param config MultipartConfigElement | 289 * @param config MultipartConfigElement |
338 * @param contextTmpDir javax.servlet.context.tempdir | 290 * @param contextTmpDir javax.servlet.context.tempdir |
339 */ | 291 */ |
340 public MultiPartInputStream (InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir) | 292 public MultiPartInputStream (InputStream in, String contentType) |
341 { | 293 { |
342 _in = new ReadLineInputStream(in); | 294 _in = new ReadLineInputStream(in); |
343 _contentType = contentType; | 295 _contentType = contentType; |
344 _config = config; | |
345 _contextTmpDir = contextTmpDir; | |
346 if (_contextTmpDir == null) | |
347 _contextTmpDir = new File (System.getProperty("java.io.tmpdir")); | |
348 | |
349 if (_config == null) | |
350 _config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath()); | |
351 } | 296 } |
352 | 297 |
353 /** | 298 /** |
354 * Get the already parsed parts. | 299 * Get the already parsed parts. |
355 * | 300 * |
453 _parts = new MultiMap<String>(); | 398 _parts = new MultiMap<String>(); |
454 | 399 |
455 //if its not a multipart request, don't parse it | 400 //if its not a multipart request, don't parse it |
456 if (_contentType == null || !_contentType.startsWith("multipart/form-data")) | 401 if (_contentType == null || !_contentType.startsWith("multipart/form-data")) |
457 return; | 402 return; |
458 | |
459 //sort out the location to which to write the files | |
460 | |
461 if (_config.getLocation() == null) | |
462 _tmpDir = _contextTmpDir; | |
463 else if ("".equals(_config.getLocation())) | |
464 _tmpDir = _contextTmpDir; | |
465 else | |
466 { | |
467 File f = new File (_config.getLocation()); | |
468 if (f.isAbsolute()) | |
469 _tmpDir = f; | |
470 else | |
471 _tmpDir = new File (_contextTmpDir, _config.getLocation()); | |
472 } | |
473 | |
474 if (!_tmpDir.exists()) | |
475 _tmpDir.mkdirs(); | |
476 | 403 |
477 String contentTypeBoundary = ""; | 404 String contentTypeBoundary = ""; |
478 int bstart = _contentType.indexOf("boundary="); | 405 int bstart = _contentType.indexOf("boundary="); |
479 if (bstart >= 0) | 406 if (bstart >= 0) |
480 { | 407 { |
538 // If blank line, end of part headers | 465 // If blank line, end of part headers |
539 if("".equals(line)) | 466 if("".equals(line)) |
540 break; | 467 break; |
541 | 468 |
542 total += line.length(); | 469 total += line.length(); |
543 if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize()) | |
544 throw new IllegalStateException ("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")"); | |
545 | 470 |
546 //get content-disposition and content-type | 471 //get content-disposition and content-type |
547 int c=line.indexOf(':',0); | 472 int c=line.indexOf(':',0); |
548 if(c>0) | 473 if(c>0) |
549 { | 474 { |
647 { | 572 { |
648 int b=0; | 573 int b=0; |
649 while((c=(state!=-2)?state:partInput.read())!=-1) | 574 while((c=(state!=-2)?state:partInput.read())!=-1) |
650 { | 575 { |
651 total ++; | 576 total ++; |
652 if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize()) | |
653 throw new IllegalStateException("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")"); | |
654 | 577 |
655 state=-2; | 578 state=-2; |
656 | 579 |
657 // look for CR and/or LF | 580 // look for CR and/or LF |
658 if(c==13||c==10) | 581 if(c==13||c==10) |
738 } | 661 } |
739 if (!lastPart) | 662 if (!lastPart) |
740 throw new IOException("Incomplete parts"); | 663 throw new IOException("Incomplete parts"); |
741 } | 664 } |
742 | 665 |
743 public void setDeleteOnExit(boolean deleteOnExit) | |
744 { | |
745 _deleteOnExit = deleteOnExit; | |
746 } | |
747 | |
748 | |
749 public boolean isDeleteOnExit() | |
750 { | |
751 return _deleteOnExit; | |
752 } | |
753 | |
754 | 666 |
755 /* ------------------------------------------------------------ */ | 667 /* ------------------------------------------------------------ */ |
756 private String value(String nameEqualsValue, boolean splitAfterSpace) | 668 private String value(String nameEqualsValue, boolean splitAfterSpace) |
757 { | 669 { |
758 /* | 670 /* |