1 16 package net.myvietnam.mvncore.web.fileupload; 17 18 import java.io.ByteArrayOutputStream ; 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.io.OutputStream ; 22 import java.io.UnsupportedEncodingException ; 23 24 85 public class MultipartStream { 86 87 89 90 93 public static final byte CR = 0x0D; 94 95 96 99 public static final byte LF = 0x0A; 100 101 102 105 public static final byte DASH = 0x2D; 106 107 108 112 public static final int HEADER_PART_SIZE_MAX = 10240; 113 114 115 118 protected static final int DEFAULT_BUFSIZE = 4096; 119 120 121 125 protected static final byte[] HEADER_SEPARATOR = { 126 CR, LF, CR, LF }; 127 128 129 133 protected static final byte[] FIELD_SEPARATOR = { 134 CR, LF}; 135 136 137 141 protected static final byte[] STREAM_TERMINATOR = { 142 DASH, DASH}; 143 144 145 148 protected static final byte[] BOUNDARY_PREFIX = { 149 CR, LF, DASH, DASH}; 150 151 152 156 private static final int KEEP_REGION_PAD = 3; 157 158 159 161 162 165 private InputStream input; 166 167 168 171 private int boundaryLength; 172 173 174 178 private int keepRegion; 179 180 181 184 private byte[] boundary; 185 186 187 190 private int bufSize; 191 192 193 196 private byte[] buffer; 197 198 199 204 private int head; 205 206 207 212 private int tail; 213 214 215 218 private String headerEncoding; 219 220 221 223 224 231 public MultipartStream() { 232 } 233 234 235 253 public MultipartStream(InputStream input, 254 byte[] boundary, 255 int bufSize) { 256 this.input = input; 257 this.bufSize = bufSize; 258 this.buffer = new byte[bufSize]; 259 260 this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length]; 263 this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length; 264 this.keepRegion = boundary.length + KEEP_REGION_PAD; 265 System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, 266 BOUNDARY_PREFIX.length); 267 System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, 268 boundary.length); 269 270 head = 0; 271 tail = 0; 272 } 273 274 275 288 public MultipartStream(InputStream input, 289 byte[] boundary) 290 throws IOException { 291 this(input, boundary, DEFAULT_BUFSIZE); 292 } 293 294 295 297 298 306 public String getHeaderEncoding() { 307 return headerEncoding; 308 } 309 310 311 318 public void setHeaderEncoding(String encoding) { 319 headerEncoding = encoding; 320 } 321 322 323 331 public byte readByte() 332 throws IOException { 333 if (head == tail) { 335 head = 0; 336 tail = input.read(buffer, head, bufSize); 338 if (tail == -1) { 339 throw new IOException ("No more data is available"); 341 } 342 } 343 return buffer[head++]; 344 } 345 346 347 357 public boolean readBoundary() 358 throws MalformedStreamException { 359 byte[] marker = new byte[2]; 360 boolean nextChunk = false; 361 362 head += boundaryLength; 363 try { 364 marker[0] = readByte(); 365 if (marker[0] == LF) { 366 return true; 373 } 374 375 marker[1] = readByte(); 376 if (arrayequals(marker, STREAM_TERMINATOR, 2)) { 377 nextChunk = false; 378 } else if (arrayequals(marker, FIELD_SEPARATOR, 2)) { 379 nextChunk = true; 380 } else { 381 throw new MalformedStreamException( 382 "Unexpected characters follow a boundary"); 383 } 384 } catch (IOException e) { 385 throw new MalformedStreamException("Stream ended unexpectedly"); 386 } 387 return nextChunk; 388 } 389 390 391 410 public void setBoundary(byte[] boundary) 411 throws IllegalBoundaryException { 412 if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) { 413 throw new IllegalBoundaryException( 414 "The length of a boundary token can not be changed"); 415 } 416 System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, 417 boundary.length); 418 } 419 420 421 436 public String readHeaders() 437 throws MalformedStreamException { 438 int i = 0; 439 byte[] b = new byte[1]; 440 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 442 int sizeMax = HEADER_PART_SIZE_MAX; 443 int size = 0; 444 while (i < HEADER_SEPARATOR.length) { 445 try { 446 b[0] = readByte(); 447 } catch (IOException e) { 448 throw new MalformedStreamException("Stream ended unexpectedly"); 449 } 450 size++; 451 if (b[0] == HEADER_SEPARATOR[i]) { 452 i++; 453 } else { 454 i = 0; 455 } 456 if (size <= sizeMax) { 457 baos.write(b[0]); 458 } 459 } 460 461 String headers = null; 462 if (headerEncoding != null) { 463 try { 464 headers = baos.toString(headerEncoding); 465 } catch (UnsupportedEncodingException e) { 466 headers = baos.toString(); 469 } 470 } else { 471 headers = baos.toString(); 472 } 473 474 return headers; 475 } 476 477 478 494 public int readBodyData(OutputStream output) 495 throws MalformedStreamException, 496 IOException { 497 boolean done = false; 498 int pad; 499 int pos; 500 int bytesRead; 501 int total = 0; 502 while (!done) { 503 pos = findSeparator(); 505 if (pos != -1) { 506 output.write(buffer, head, pos - head); 508 total += pos - head; 509 head = pos; 510 done = true; 511 } else { 512 if (tail - head > keepRegion) { 515 pad = keepRegion; 516 } else { 517 pad = tail - head; 518 } 519 output.write(buffer, head, tail - head - pad); 521 522 total += tail - head - pad; 524 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 525 526 head = 0; 528 bytesRead = input.read(buffer, pad, bufSize - pad); 529 530 if (bytesRead != -1) { 532 tail = pad + bytesRead; 533 } else { 534 output.write(buffer, 0, pad); 538 output.flush(); 539 total += pad; 540 throw new MalformedStreamException( 541 "Stream ended unexpectedly"); 542 } 543 } 544 } 545 output.flush(); 546 return total; 547 } 548 549 550 562 public int discardBodyData() 563 throws MalformedStreamException, 564 IOException { 565 boolean done = false; 566 int pad; 567 int pos; 568 int bytesRead; 569 int total = 0; 570 while (!done) { 571 pos = findSeparator(); 573 if (pos != -1) { 574 total += pos - head; 576 head = pos; 577 done = true; 578 } else { 579 if (tail - head > keepRegion) { 582 pad = keepRegion; 583 } else { 584 pad = tail - head; 585 } 586 total += tail - head - pad; 587 588 System.arraycopy(buffer, tail - pad, buffer, 0, pad); 590 591 head = 0; 593 bytesRead = input.read(buffer, pad, bufSize - pad); 594 595 if (bytesRead != -1) { 597 tail = pad + bytesRead; 598 } else { 599 total += pad; 603 throw new MalformedStreamException( 604 "Stream ended unexpectedly"); 605 } 606 } 607 } 608 return total; 609 } 610 611 612 620 public boolean skipPreamble() 621 throws IOException { 622 System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); 624 boundaryLength = boundary.length - 2; 625 try { 626 discardBodyData(); 628 629 return readBoundary(); 632 } catch (MalformedStreamException e) { 633 return false; 634 } finally { 635 System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2); 637 boundaryLength = boundary.length; 638 boundary[0] = CR; 639 boundary[1] = LF; 640 } 641 } 642 643 644 655 public static boolean arrayequals(byte[] a, 656 byte[] b, 657 int count) { 658 for (int i = 0; i < count; i++) { 659 if (a[i] != b[i]) { 660 return false; 661 } 662 } 663 return true; 664 } 665 666 667 677 protected int findByte(byte value, 678 int pos) { 679 for (int i = pos; i < tail; i++) { 680 if (buffer[i] == value) { 681 return i; 682 } 683 } 684 685 return -1; 686 } 687 688 689 697 protected int findSeparator() { 698 int first; 699 int match = 0; 700 int maxpos = tail - boundaryLength; 701 for (first = head; 702 (first <= maxpos) && (match != boundaryLength); 703 first++) { 704 first = findByte(boundary[0], first); 705 if (first == -1 || (first > maxpos)) { 706 return -1; 707 } 708 for (match = 1; match < boundaryLength; match++) { 709 if (buffer[first + match] != boundary[match]) { 710 break; 711 } 712 } 713 } 714 if (match == boundaryLength) { 715 return first - 1; 716 } 717 return -1; 718 } 719 720 725 public String toString() { 726 StringBuffer sbTemp = new StringBuffer (); 727 sbTemp.append("boundary='"); 728 sbTemp.append(String.valueOf(boundary)); 729 sbTemp.append("'\nbufSize="); 730 sbTemp.append(bufSize); 731 return sbTemp.toString(); 732 } 733 734 738 public static class MalformedStreamException 739 extends IOException { 740 744 public MalformedStreamException() { 745 super(); 746 } 747 748 754 public MalformedStreamException(String message) { 755 super(message); 756 } 757 } 758 759 760 763 public static class IllegalBoundaryException 764 extends IOException { 765 769 public IllegalBoundaryException() { 770 super(); 771 } 772 773 779 public IllegalBoundaryException(String message) { 780 super(message); 781 } 782 } 783 784 785 787 788 850 } 851 | Popular Tags |