Abisco title> head> html> ------------ ---------------- 7d15340138 - It can be seen that the HTTP request contains all form inputs, including uploaded files. The separation of these input data is implemented by a separator. The separator consists of a series of "-" characters and a random number.
In the above example, the separator is "-------------------------- 7D15340138. The last separator ends the request body, and there are two "-" symbols behind this separator. For non-file type input data, the separator follows the following line: Content-Disposition: form-data; name = inputname. Wherein InputName is the name of the form element. For example: content-disposition: form-data; name = "author". Behind this line of content, followed by two consecutive carriage return and form elements. For file type input domain, there are two lines of content behind the separator. The first line of content contains the name of the input element and the full path to the client on the client. As the content in the above example is "content-disposition: form-data; name =" filename "; filename =" C: / 123Data / Abisco. HTML "". This line of content pointed out that the name of the file input element is filename, the path to the file is "c: /123data/abisco.html". Note that the Windows browser sets the file path, and UNIX / Linux and the Mac browser only send file names. The second line contains the content type of the file, so its specific content is related to the uploaded file. The contents of the second line in this example are "content-type: text / html". Like non-file input elements, the file content is officially started after two consecutive carriage return. As is well known, JavaBean is a software component of the Java platform. The upload function to be implemented below is implemented with JavaBean, so it can easily apply to any application that requires file upload functions.
The following code listing: package com.brainysoftware.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.ServletInputStream; import java.util.Dictionary; import java.util.Hashtable; import java.io.PrintWriter; import java .io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class FileUploadBean {private String savePath, filepath, filename, contentType; private Dictionary fields; public String getFilename () {return filename;} public String getFilepath () {return filepath;} public void setSavePath (String savePath) {this.savePath = savePath;} public String getContentType () {return contentType;} public String getFieldValue (String fieldName) {if (fields == null || fieldName = = NULL) RETURN NULL; RETURN (String) Fields.get (FieldName);} Private void setFileName (String s) {if (s == null) return; int pos = s.indexof ("filename = /"); IF (POS! = -1) {filepath = s.substring (POS 10, S.Length () - 1); // Windows browser sends full file path and name // but Linux / UNIX and Mac browser Just send file name POS = FI LePath.lastIndexof ("//"); if (pOS! = -1) filename = filepath.substring (POS 1); else filename = filepath;}} private void setContentType (String s) {ix (s == null Return; int pos = s.indexof (":"); if (pOS! = -1) ContentType = s.substring (POS 2, S.Length ());} PUBLIC VOID DOUPLOAD (HTTPSERVLETREQUEST REQUEST) Throws oException {Servletinputstream in = request.getinputStream (); byte [] line = new byte [128]; int i = in.readline (line 0, 128); if (i <3) return; int boundarylength = i - 2; String boundary = new string (line, 0, bousarylength); // - 2 Discard Change Character Fields = New HashTable ();
While (i! = -1) {string newline = new string (line, 0, i); if (newline.StartSwith ("Content-Disposition: Form-Data; Name = /")) {IF (Newline.indexof ("FileName = /" ")! = -1) {setFileName (New String (Line, 0, I-2)); if (filename == null) return; // file content i = in.readline (line, 0, 128); setContentType (New String (Line, 0, I-2); i = in.readline (line, 0, 128); // 空 行 = in.readline (line, 0, 128); NEWLINE = New String (line, 0, i); PrintWriter PW = New PrintWriter (New FileWriter ((SavePath == Null ((SavePath) FileName)); while (i! = -1&&! NEWLINE.STARTSWITH (Boundary)) {// File content The last line contains a change character / / thus we must check if the current line is the most //, one line i = in.readline (Line, 0, 128); if ((i == Boundarylength 2 || i == Boundarylength 4) && (new string (line, 0, i) .startswith (boundary))) PW.Print (Newline.Substring (0, newline.length () - 2) Else Pw.Print (newline); newline = new string (line, 0, i);} pw.close ();} else {// Normal form input element // Get input element name INT POS = newline.indexof ("Name = /" "); string fieldname = newline.substring (POS 6, N EWLINE.LENGTH () - 3); i = in.readline (line, 0, 128); i = in.readline (line, 0, 128); newline = new string (line, 0, i); stringbuffer fieldValue = New stringbuffer (128); while (i! = -1 &&! newline.startswith (boundary)) {// The last line contains a charming character / / thus we must check if the current line is the last line i = in.readline (Line, 0, 128); IF ((i == Boundarylength 2 || i == Boundarylength 4) && (New String (Line, 0, i) .StartSwith (Boundary)) FieldValue.Append (Newline.Substring (0 , NewLine.Length () - 2)); Else FieldValue.Append (Newline = New String (Line, 0, i);
} Fields.Put (FieldName, FieldValue.Tostring ());}} i = in.readline (line, 0, 128);}}}} The first line of code is a package declaration, if you don't want this class from any Package, you can delete this line of code. The next few lines of code declares the various classes and interfaces to which the JavaBean wants. The FileUploadBean class has 5 private properties (domains), 6 common methods, and 2 private methods. The 5 domains of the property FileUploadBean class are private, they are: Private String SavePath This domain specifies which path to the server after the file is uploaded. The value of SavePath is set with the setsavepath method. This value should be set before calling the DoupLoad method; if there is no setting, the uploaded file will be saved to the server's default directory. Private string filepath This domain specifies the full path to the upload file on the client. The value of FilePath is set by the DOUPLOAD method, and the GetFilePath method can be used in the JSP page or the servlet to get the value of the FilePath domain. For browsers under non-Windows, this value is equal to FILENAME. Private string filename This domain is the name of the upload file. The value of filename is set by the setFileName method. Calling the getFileName method in the JSP or Servlet can get the value of the FileName field. Private String ContentType This domain is the content type of uploading files. The value of ContentType is set by the DOUPLOAD method, you can use the getContentType method to get the value of the ContentType field. The Private Dictionary Fields Fields domain saves the name / value pair of users entering data in the form. Calling the getFieldValue method You can get the value of the form input element. Methods of the four PUBLIC types of public types are used to return the private domain of the FileUPloadBean object, which is: getFilePath, getFileName, getContentType, and getFieldValue. Public String getFilePath () Returns the value of the FilePath private domain. Public String getFileName () Returns the value of the FileName private domain. Public String getContentType () Returns the value of the ContentType private domain. Public String getFieldValue (String FieldName) Returns the value of the specified input element in the HTML form, and the name of the element is specified by the fieldName parameter. Public void setsavePath (String SavePath) Use this method to specify the name of the directory that holds the upload file on the server. Public void dolpload (httpservletRequest request) throws ioException DOUPLOAD is the most important way in the FileUploadBean class. Its task has two: first, it extracts the name and value of the input domain from the HTML form and saves the Dictionary object; second, the DoupLoad method extracts the uploaded file, save this file to the path specified by SavePath, and Assign the name, path, and content type of the file to the FileName, FilePath, and ContentType fields, respectively. Private void setContentType (String S) is called by a DOUPLOAD method. The setContentType method extracts the content type of upload files from the original byte data.
Private Void SetFileName (String S) is called by a dolpload method. The setFileName method extracts the file path and the name from the original byte data. The parameters for the DoupLoad method are the HTTPServletRequest object created by the servlet / JSP container. The HTTPSERVLETREQUEST object describes the HTTP request to extract the HTML form element name-value pair and upload files must be processed. The DoupLoad method first gets a servletinputStream object through the GetInputStream method of the HTTPSERVLETREQUEST object. As mentioned earlier, each form element is separated by the delimiter and a set of carriage return. Therefore, we can read the contents of the HTTPSERVLETREQUEST object in a line. The following line code defines a BYTE array named line: byte [] line = new byte [128]; then we read the first line of the HTTPSERVLETREQUEST object content with the READLINE method of the servletinputstream object: int i = in.readline (Line, 0, 128); The first line should be a delimiter, and if there is no error, its length should be greater than 3. If it is less than 3, we can think that there is a mistake, the DoupLoad method should return immediately: if (i <3) return; the length of the delimiter and the delimiter is very important, from this article you can see this. The delimiter is over the end of a set of carriage return, so its actual length is less than the number of bytes returned by the Readline method. INT boundarylength = i - 2; Discard the last 2 return line of the BYTE array LINE to get the delimiter: String Boundary = New String (Line, 0, Boundarylength); Next, the Fields domain is instantiated into a HashTable object. This HashTable object will be used to save the name / value pair of HTML form elements. Fields = new hashtable (); Since we already have a delimiter, we can start to extract the value of the form element. The specific method is to read the contents of the HTTPServletRequest object with a While loop until the content ending the readline method returns -1. All form elements start with delimiter, followed by "Content-Disposition" line, this line begins with the following characters: content-disposition: form-data; Name = Form element has two types: file, non-file ( Ordinary form elements such as Text or Hidden elements). The difference between these two form elements is that the file elements include string "filename =" filename "". Thus, we can use this information to distinguish files and non-file form input elements, code as follows: if (newline.startswith ("Content-Disposition: form-data; name = /")) {if (newline .indexof ("FileName = /")! = -1) {// file type input element // Add code with the extracted file..} Else {// Ordinary form input element // Here The code of the form element...}} Now let's take a look at the code for extracting the file content. The file path is included behind "Content-Disposition".
To extract file paths and file names, the DOUPLOAD method calls the SETFILENAME private method. The setFileName method extracts the file path and file name information and assigns them to the FilePath and FileName fields. After calling the setFileName method, the FileName domain should no longer be NULL. If the FileName field is still null, the problem is encountered, the DoupLoad method returns directly. If (filename == null) return; the next line after the "Content-Disposition" line is the content type line. Therefore, the DOUPLOAD method then invokes the Readline method and then calls the setContentType private method. The setContentType method is similar to the SetFileName method, which extracts the content type of upload files from the original byte data and saves to the ContentType field. The next line of the following lines is blank, so the program is called again. i = in.readline (Line, 0, 128); Next start the real file content. We should first write files to disk through the PrintWriter object. PrintWriter PW = New PrintWriter (New FileWriter ((SavePath == Null "": SavePath) filename)))); Upload file Save to which location depends on whether the SavePath domain has been set. If the SavePath domain is not set, its value is null, then the file will be saved to the default directory; if the SavePath field has been set, its value is not null, then the uploaded file is saved to the directory it specified. Then we can extract the contents of the file. The specific method is to use the While loop, read into a row per cycle and write it into the disk through the PrintWriter output method. But we know that the last line of the file contains two carriage return line symbols, so the byte data saved to the disk should not contain both characters. Therefore, if the read line is not the last line of the file, we write all the byte data read into the disk; if the read row is already the last line of the file, the byte data written to the disk should be subtracted to minus the last two Character. However, we don't know the size of the file. We only know that the next line of the file content is also a delimiter; or if the file is the last HTML form element, the next line is the delimiter plus two tends. Line characters. Therefore, as long as the next row content is a delimiter, we know when you should end the While loop. This is the reason why it is important to say that we must use the delimiter. Although we can read the next row and then check it if it is a delimiter, however, due to the overhead of the string operation, in order to reduce the string operation, we compare the length of the byte array read in Readline. The latter should be equal to BoundaryLength 2; or if it is the last line in the httpservletRequest object, it should be equal to Boundarylength 4 because of the last two short-stroke characters. Since the content can be as long as the delimiter, we will compare it to the delimiter after the length matches. This is a very important reason to mention BoundaryLength.
The implementation code of the entire process is as follows: While (i! = -1 &&! Newline.startswith (boundary)) {i = in.readline (line, 0, 128); if ((i == Boundarylength 2 || == Boundarylength 4) && (new string (line, 0, i) .startswith (boundary))) PW.Print (Newline.Substring (0, newline.Length () - 2); else PW.Print (Newline ); newline = new string (line, 0, i);} After saving the file to disk, we turn off PrintWriter. PW.Close (); non-file form elements can also be extracted with similar methods. The difference is that we will no longer write data to disk, but save the name-value to Dictionary objects. Fields.put (FieldName, FieldValue.toTRING ()); After the application instance is compiled, we can use it from the servlet or JSP page. You may use bean in a servlet / jsp environment in Tomcat, deploying the easiest way to deploy the Class file into a JAR file, but put the JAR file in the Tomcat's lib directory. To make Tomcat to the JAR file, you must restart Tomcat. Below is an HTML file and a JSP file, which demonstrates the application of this bean. The HTML file contains a form and several input elements:
file upload title> head>