1 16 package net.myvietnam.mvncore.web.fileupload; 17 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.OutputStream ; 21 import java.io.UnsupportedEncodingException ; 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.List ; 25 import java.util.Map ; 26 import javax.servlet.http.HttpServletRequest ; 27 28 import net.myvietnam.mvncore.web.fileupload.servlet.ServletRequestContext; 29 30 53 public abstract class FileUploadBase { 54 55 57 58 72 public static final boolean isMultipartContent(RequestContext ctx) { 73 String contentType = ctx.getContentType(); 74 if (contentType == null) { 75 return false; 76 } 77 if (contentType.toLowerCase().startsWith(MULTIPART)) { 78 return true; 79 } 80 return false; 81 } 82 83 84 95 public static final boolean isMultipartContent(HttpServletRequest req) { 96 if (!"post".equals(req.getMethod().toLowerCase())) { 97 return false; 98 } 99 String contentType = req.getContentType(); 100 if (contentType == null) { 101 return false; 102 } 103 if (contentType.toLowerCase().startsWith(MULTIPART)) { 104 return true; 105 } 106 return false; 107 } 108 109 110 112 113 116 public static final String CONTENT_TYPE = "Content-type"; 117 118 119 122 public static final String CONTENT_DISPOSITION = "Content-disposition"; 123 124 125 128 public static final String FORM_DATA = "form-data"; 129 130 131 134 public static final String ATTACHMENT = "attachment"; 135 136 137 140 public static final String MULTIPART = "multipart/"; 141 142 143 146 public static final String MULTIPART_FORM_DATA = "multipart/form-data"; 147 148 149 152 public static final String MULTIPART_MIXED = "multipart/mixed"; 153 154 155 159 public static final int MAX_HEADER_SIZE = 1024; 160 161 162 164 165 169 private long sizeMax = -1; 170 171 172 175 private String headerEncoding; 176 177 178 180 181 186 public abstract FileItemFactory getFileItemFactory(); 187 188 189 194 public abstract void setFileItemFactory(FileItemFactory factory); 195 196 197 205 public long getSizeMax() { 206 return sizeMax; 207 } 208 209 210 218 public void setSizeMax(long sizeMax) { 219 this.sizeMax = sizeMax; 220 } 221 222 223 231 public String getHeaderEncoding() { 232 return headerEncoding; 233 } 234 235 236 244 public void setHeaderEncoding(String encoding) { 245 headerEncoding = encoding; 246 } 247 248 249 251 252 266 public List parseRequest(HttpServletRequest req) 267 throws FileUploadException { 268 return parseRequest(new ServletRequestContext(req)); 269 } 270 271 283 public List parseRequest(RequestContext ctx) 284 throws FileUploadException { 285 if (ctx == null) { 286 throw new NullPointerException ("ctx parameter"); 287 } 288 289 ArrayList items = new ArrayList (); 290 String contentType = ctx.getContentType(); 291 292 if ((null == contentType) 293 || (!contentType.toLowerCase().startsWith(MULTIPART))) { 294 throw new InvalidContentTypeException( 295 "the request doesn't contain a " 296 + MULTIPART_FORM_DATA 297 + " or " 298 + MULTIPART_MIXED 299 + " stream, content type header is " 300 + contentType); 301 } 302 int requestSize = ctx.getContentLength(); 303 304 if (requestSize == -1) { 305 throw new UnknownSizeException( 306 "the request was rejected because its size is unknown"); 307 } 308 309 if (sizeMax >= 0 && requestSize > sizeMax) { 310 throw new SizeLimitExceededException( 311 "the request was rejected because its size (" + requestSize 312 + ") exceeds the configured maximum (" + sizeMax + ")", 313 requestSize, sizeMax); 314 } 315 316 String charEncoding = headerEncoding; 317 if (charEncoding == null) { 318 charEncoding = ctx.getCharacterEncoding(); 319 } 320 321 try { 322 byte[] boundary = getBoundary(contentType); 323 if (boundary == null) { 324 throw new FileUploadException( 325 "the request was rejected because " 326 + "no multipart boundary was found"); 327 } 328 329 InputStream input = ctx.getInputStream(); 330 331 MultipartStream multi = new MultipartStream(input, boundary); 332 multi.setHeaderEncoding(charEncoding); 333 334 boolean nextPart = multi.skipPreamble(); 335 while (nextPart) { 336 Map headers = parseHeaders(multi.readHeaders()); 337 String fieldName = getFieldName(headers); 338 if (fieldName != null) { 339 String subContentType = getHeader(headers, CONTENT_TYPE); 340 if (subContentType != null && subContentType 341 .toLowerCase().startsWith(MULTIPART_MIXED)) { 342 byte[] subBoundary = getBoundary(subContentType); 344 multi.setBoundary(subBoundary); 345 boolean nextSubPart = multi.skipPreamble(); 346 while (nextSubPart) { 347 headers = parseHeaders(multi.readHeaders()); 348 if (getFileName(headers) != null) { 349 FileItem item = 350 createItem(headers, false); 351 OutputStream os = item.getOutputStream(); 352 try { 353 multi.readBodyData(os); 354 } finally { 355 os.close(); 356 } 357 items.add(item); 358 } else { 359 multi.discardBodyData(); 362 } 363 nextSubPart = multi.readBoundary(); 364 } 365 multi.setBoundary(boundary); 366 } else { 367 FileItem item = createItem(headers, 368 getFileName(headers) == null); 369 OutputStream os = item.getOutputStream(); 370 try { 371 multi.readBodyData(os); 372 } finally { 373 os.close(); 374 } 375 items.add(item); 376 } 377 } else { 378 multi.discardBodyData(); 380 } 381 nextPart = multi.readBoundary(); 382 } 383 } catch (IOException e) { 384 throw new FileUploadException( 385 "Processing of " + MULTIPART_FORM_DATA 386 + " request failed. " + e.getMessage()); 387 } 388 389 return items; 390 } 391 392 393 395 396 404 protected byte[] getBoundary(String contentType) { 405 ParameterParser parser = new ParameterParser(); 406 parser.setLowerCaseNames(true); 407 Map params = parser.parse(contentType, ';'); 409 String boundaryStr = (String ) params.get("boundary"); 410 411 if (boundaryStr == null) { 412 return null; 413 } 414 byte[] boundary; 415 try { 416 boundary = boundaryStr.getBytes("ISO-8859-1"); 417 } catch (UnsupportedEncodingException e) { 418 boundary = boundaryStr.getBytes(); 419 } 420 return boundary; 421 } 422 423 424 432 protected String getFileName(Map headers) { 433 String fileName = null; 434 String cd = getHeader(headers, CONTENT_DISPOSITION); 435 if (cd != null) { 436 String cd_lower = cd.toLowerCase(); if (cd_lower.startsWith(FORM_DATA) || cd_lower.startsWith(ATTACHMENT)) { 438 ParameterParser parser = new ParameterParser(); 439 parser.setLowerCaseNames(true); 440 Map params = parser.parse(cd, ';'); 442 if (params.containsKey("filename")) { 443 fileName = (String ) params.get("filename"); 444 if (fileName != null) { 445 fileName = fileName.trim(); 446 } else { 447 fileName = ""; 451 } 452 } 453 } 454 } 455 return fileName; 456 } 457 458 459 467 protected String getFieldName(Map headers) { 468 String fieldName = null; 469 String cd = getHeader(headers, CONTENT_DISPOSITION); 470 if (cd != null && cd.toLowerCase().startsWith(FORM_DATA)) { 471 472 ParameterParser parser = new ParameterParser(); 473 parser.setLowerCaseNames(true); 474 Map params = parser.parse(cd, ';'); 476 fieldName = (String ) params.get("name"); 477 if (fieldName != null) { 478 fieldName = fieldName.trim(); 479 } 480 } 481 return fieldName; 482 } 483 484 485 497 protected FileItem createItem(Map headers, 498 boolean isFormField) 499 throws FileUploadException { 500 return getFileItemFactory().createItem(getFieldName(headers), 501 getHeader(headers, CONTENT_TYPE), 502 isFormField, 503 getFileName(headers)); 504 } 505 506 507 519 protected Map parseHeaders(String headerPart) { 520 Map headers = new HashMap (); 521 char[] buffer = new char[MAX_HEADER_SIZE]; 522 boolean done = false; 523 int j = 0; 524 int i; 525 String header, headerName, headerValue; 526 try { 527 while (!done) { 528 i = 0; 529 while (i < 2 532 || buffer[i - 2] != '\r' || buffer[i - 1] != '\n') { 533 buffer[i++] = headerPart.charAt(j++); 534 } 535 header = new String (buffer, 0, i - 2); 536 if (header.equals("")) { 537 done = true; 538 } else { 539 if (header.indexOf(':') == -1) { 540 continue; 542 } 543 headerName = header.substring(0, header.indexOf(':')) 544 .trim().toLowerCase(); 545 headerValue = 546 header.substring(header.indexOf(':') + 1).trim(); 547 if (getHeader(headers, headerName) != null) { 548 headers.put(headerName, 551 getHeader(headers, headerName) + ',' 552 + headerValue); 553 } else { 554 headers.put(headerName, headerValue); 555 } 556 } 557 } 558 } catch (IndexOutOfBoundsException e) { 559 } 562 return headers; 563 } 564 565 566 576 protected final String getHeader(Map headers, 577 String name) { 578 return (String ) headers.get(name.toLowerCase()); 579 } 580 581 582 585 public static class InvalidContentTypeException 586 extends FileUploadException { 587 591 public InvalidContentTypeException() { 592 super(); 593 } 594 595 601 public InvalidContentTypeException(String message) { 602 super(message); 603 } 604 } 605 606 607 610 public static class UnknownSizeException 611 extends FileUploadException { 612 616 public UnknownSizeException() { 617 super(); 618 } 619 620 626 public UnknownSizeException(String message) { 627 super(message); 628 } 629 } 630 631 632 635 public static class SizeLimitExceededException 636 extends FileUploadException { 637 640 private long actual; 641 642 645 private long permitted; 646 647 651 public SizeLimitExceededException() { 652 super(); 653 } 654 655 661 public SizeLimitExceededException(String message) { 662 super(message); 663 } 664 665 673 public SizeLimitExceededException(String message, long actual, 674 long permitted) { 675 super(message); 676 this.actual = actual; 677 this.permitted = permitted; 678 } 679 680 685 public long getActualSize() { 686 return actual; 687 } 688 689 694 public long getPermittedSize() { 695 return permitted; 696 } 697 } 698 699 } 700 | Popular Tags |