Learn Common-upload source code, understand the principle of uploading

Source: Internet
Author: User

Previously, we described how to upload a file using only a piece of code. I have tried several times recently to find out that this is a problem.
For example, to upload a file with the original file as follows:

Using JSP upload found that the file becomes the following, the image below the pixel is not.

Then I tried again with common-upload1.2, can upload normally, the file will not be changed. How could it be this way?

To solve this problem to understand the background, the browser sends an HTTP request when the general post method will put the input control name and value into a string as the request body to the server. A similar message is added to the request header for HTTP requests for method= "POST" enctype= "multipart/form-data" such as uploading files:
content-length 5137
Content-type Multipart/form-data; boundary=---------------------------203012335616103


This boundary represents the delimiter in the request body, which is the entire request body that packs the actual file contents with the value of the delimiter.
The request body is in the following format:

-----------------------------221842651231148
Content-disposition:form-data; Name= "Upfile"; Filename= "Srcfile (2). jpg"
Content-type:image/jpeg
<!-Upload file contents here (byte array)-"
-----------------------------221842651231148


You can see the contents of the delimiter in addition to the file bytes, but also before the contents of the file to add some basic information.


The following analysis of why JSP did not upload files correctly, first look at the JSP upload code:
1. Get all byte arrays of contextlength
in = new DataInputStream (Request.getinputstream ());
int datalength = Request.getcontentlength ();
while (Totalbytesread < datalength) {
Byteread = In.read (Databytes, Totalbytesread,
DATALENGTH);
Totalbytesread + = Byteread;
}
2. Where to start and where to end the file
int POS;
pos = File.indexof ("filename=\");
pos = File.indexof ("\ n", POS) + 1;
pos = File.indexof ("\ n", POS) + 1;
pos = File.indexof ("\ n", POS) + 1;
int boundarylocation = file.indexof (boundary, POS)-4; int startpos = ((file.substring (0, POS)). GetBytes ()). length;
int endpos = ((file.substring (0, boundarylocation))
. GetBytes ()). length;
3. Convert the byte array from start position to end position to file, output to disk.
FileOutputStream fos=new FileOutputStream (fileName)
Fos.write (Databytes, Startpos, (Endpos-startpos));
Fileout.close ();

So common-upload how to do it, the code is more, here only some key logic code:
1. Parse the file and remove the delimiter in the request header
Rquest object to Fileitemstreamiterator object
ORG.APACHE.COMMONS.FILEUPLOAD.SERVLET.SERVLETFILEUPLOAD[LINE:146]
Fileitemiterator FII = new Servletfileupload (). Getitemiterator (Request);
Take header
ORG.APACHE.COMMONS.FILEUPLOAD.FILEUPLOADBASE[LINE:976]
Fileitemheaders headers = getparsedheaders (Multi.readheaders ());
Take the delimiter in the ContentType in the header
ORG.APACHE.COMMONS.FILEUPLOAD.FILEUPLOADBASE[LINE:397]
Protected byte[] Getboundary (String contentType) {


2. Find valid data between delimiters in the request body.
The delimiter method is as follows, the byte in buffer is exactly the same as the byte in the boundary to be considered a delimiter:
ORG.APACHE.COMMONS.FILEUPLOAD.MULTIPARTSTREAM[LINE:708]
protected int Findseparator () {
int first;
int match = 0;
int maxpos = Tail-boundarylength;
for (first = head;
(First <= Maxpos) && (Match! = boundarylength);
first++) {
First = Findbyte (Boundary[0], first);
if (first = =-1 | | (First > Maxpos)) {
return-1;
}
for (match = 1; match < boundarylength; match++) {
if (Buffer[first + match]! = Boundary[match]) {
Break
}
}
}
if (match = = Boundarylength) {
return first-1;
}
return-1;
}
3. Summarize each valid piece of data separated by a delimiter into a byte array and finally form a file. The following classes and methods are used to summarize:
ORG.APACHE.COMMONS.FILEUPLOAD.MULTIPARTSTREAM[LINE:784]
public class Iteminputstream extends InputStream implements Closeable
public int read (byte[] b, int off, int len) throws IOException {
if (closed) {
throw new Fileitemstream.itemskippedexception ();
}
if (len = = 0) {
return 0;
}
int res = available ();
if (res = = 0) {
res = makeavailable ();
if (res = = 0) {
return-1;
}
}
res = math.min (res, Len);
System.arraycopy (buffer, head, B, off, RES);
Head + = res;
Total + = res;
return res;
}
The final total count is the final file byte count, which can then be written as a file using FileOutputStream. This available function and how to overwrite the InputStream are not quite clear, but also need to understand the flow of the underlying process.
It can be seen from above that the JSP upload code error is mainly caused by incorrect delimiter recognition.

Learn Common-upload source code, understand the principle of uploading

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.