Three methods for file upload-Java and java
Because of the need to upload files in the project (SpringMvc started in jetty embedded) in which you are in charge, you have never touched on the java file upload and are vague about the Http protocol, therefore, this document uses a progressive approach to learn the principles and practices of file upload. This blog focuses on practice.
1. Introduction to Http principles
HTTP is an object-oriented protocol at the application layer. It is applicable to distributed hypermedia information systems due to its simple and fast method. It proposed in 1990 that, after several years of use and development, it has been continuously improved and expanded. Currently, the sixth version of HTTP/1.0 is used in WWW, standardization of HTTP/1.1 is in progress, and suggestions for HTTP-NG (Next Generation of HTTP) have been put forward.
Simply put, it is a communication specification based on the application layer: both parties need to communicate, and everyone must abide by this specification, which is the HTTP protocol.
1. features:
(1) supports the customer/Server mode.
(2) simple and fast: when a customer requests a service from the server, they only need to send the request method and path. Common Request methods include GET, HEAD, and POST. Each method specifies the type of contact between the customer and the server. Because the HTTP protocol is simple, the program size of the HTTP server is small, so the communication speed is fast.
(3) Flexibility: HTTP allows transmission of any type of data objects. The Type being transferred is marked by Content-Type.
(4) No connection: No connection means that only one request is allowed for each connection. After the server processes the customer's request and receives the customer's response, the connection is disconnected. This method can save transmission time.
(5) stateless: HTTP is stateless. Stateless means that the Protocol has no memory for transaction processing. The lack of status means that if subsequent processing requires the previous information, it must be re-transmitted, which may increase the amount of data transmitted each connection. On the other hand, when the server does not need previous information, its response is faster.
Note: (4) (5) is a frequently used interview question. Although the HTTP protocol (Application Layer) is connectionless and stateless, the TCP protocol (Transport Layer) It depends on is usually connectedand stateful, while the TCP protocol (Transport Layer) it also depends on the IP protocol (Network Layer ).
2. HTTP message structure
(1) Request messages are divided into three parts. The first part is the Request line, the second part is the http header, and the third part is the body. There is a blank line between the header and the body. The structure is as follows:
(2) The structure of the Response Message is basically the same as that of the Request message. It is also divided into three parts: The first part is the request line status line, the second part is the request header message body, and the third part is the body. There is also a blank line between the header and body. The structure is as follows:
The following are the Request message bodies and Response Message bodies that use Fiddler to capture the Request for baidu:
Because no form information is input, the message body of the request is empty. You can try it on the login page.
First come here, the knowledge of the HTTP protocol is very rich on the internet, and I will not discuss it here.
Ii. Three implementations of File Upload
1. Jsp/servlet File Upload
This is the most common and simplest method.
(1) Jsp page for File Upload
(2) FileUploadServlet
Import java. io. file; import java. io. fileOutputStream; import java. io. IOException; import java. io. inputStream; import javax. servlet. servletException; import javax. servlet. http. httpServlet; import javax. servlet. http. httpServletRequest; import javax. servlet. http. httpServletResponse; import org. apache. log4j. logger; // @ WebServlet (name = "FileLoadServlet", urlPatterns = {"/fileload"}) public class FileLoadServlet Extends HttpServlet {private static Logger logger = Logger. getLogger (FileLoadServlet. class);/***/private static final long serialVersionUID = 1302377908285976972L; @ Overrideprotected void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {logger.info ("------------ FileLoadServlet ------------"); if (request. getContentLength ()> 0) {InputStrea M inputStream = null; FileOutputStream outputStream = null; try {inputStream = request. getInputStream (); // set the time to a new file in milliseconds to prevent the name from being long now = System. currentTimeMillis (); File file = new File ("c:/", "file-" + now + ". txt "); file. createNewFile (); outputStream = new FileOutputStream (file); byte temp [] = new byte [1024]; int size =-1; while (size = inputStream. read (temp ))! =-1) {// 1 kb is read each time until outputStream is read. write (temp, 0, size);} logger.info ("File load success. ");} catch (IOException e) {logger. warn ("File load fail. ", e); request. getRequestDispatcher ("/fail. jsp "). forward (request, response);} finally {outputStream. close (); inputStream. close () ;}} request. getRequestDispatcher ("/succ. jsp "). forward (request, response );}}
The configuration of FileUploadServlet is more convenient by using the servlet3.0 annotation.
<servlet> <servlet-name>FileLoadServlet</servlet-name> <servlet-class>com.juxinli.servlet.FileLoadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FileLoadServlet</servlet-name> <url-pattern>/fileload</url-pattern> </servlet-mapping>
(3) Running Effect
Click "submit"
Page to file upload successful page, then go to disk C to see, found more than a file: file-1433417127748.txt, This is just uploaded file
Let's open it and see that it is a little different from the original text.
Based on the HTTP message structure mentioned above, it is not difficult to find that these texts are the "Request Message Body" after the "Request Header" is removed ". Therefore, if you want to get the same text as the uploaded file, you still need some string operations, which will be left to everyone.
In addition, you can try uploading multiple files on a Jsp page, which will be different.
2. Simulate Post request/servlet for File Upload
We just used Jsp pages to upload files. If the client is not a webapp project, it is clear that the method we just used is a little well-formed.
Here we have another idea. Since we can upload files by clicking on the page, why can't we use HttpClient to simulate a browser's request to upload files. For more information, see HttpClient.
(1) Start the servlet service.
(2) The FileLoadClient that simulates the request
Import java. io. bufferedReader; import java. io. file; import java. io. inputStream; import java. io. inputStreamReader; import org. apache. commons. httpclient. httpClient; import org. apache. commons. httpclient. httpStatus; import org. apache. commons. httpclient. methods. postMethod; import org. apache. commons. httpclient. methods. multipart. filePart; import org. apache. commons. httpclient. methods. multipart. multipartRequestEnti Ty; import org. apache. commons. httpclient. methods. multipart. part; import org. apache. log4j. logger; public class FileLoadClient {private static Logger logger = Logger. getLogger (FileLoadClient. class); public static String fileload (String url, File file) {String body = "{}"; if (url = null | url. equals ("") {return "parameter illegal";} if (! File. exists () {return "the file name to be uploaded does not exist";} PostMethod postMethod = new PostMethod (url); try {// FilePart: class used to upload files, file: FilePart fp = new FilePart ("file", file); Part [] parts = {fp}; // for MIME-type requests, httpclient we recommend that you use MulitPartRequestEntity to wrap MultipartRequestEntity mre = new multipartreququestentity (parts, postMethod. getParams (); postMethod. setRequestEntity (mre); HttpClient client = new HttpClient (); // Because the file to be uploaded may be large, set the maximum connection timeout value here. getHttpConnectionManager (). getParams (). setConnectionTimeout (50000); int status = client.exe cuteMethod (postMethod); if (status = HttpStatus. SC _ OK) {InputStream inputStream = postMethod. getResponseBodyAsStream (); BufferedReader br = new BufferedReader (new InputStreamReader (inputStream); StringBuffer stringBuffer = new StringBuffer (); String str = ""; wh Ile (str = br. readLine ())! = Null) {stringBuffer. append (str);} body = stringBuffer. toString () ;}else {body = "fail" ;}} catch (Exception e) {logger. warn ("File Upload exception", e) ;}finally {// release the connection postMethod. releaseConnection () ;}return body;} public static void main (String [] args) throws Exception {String body = fileload ("http: // localhost: 8080/jsp_upload-servlet/fileload ", new File (" C:/1111.txt"); System. out. println (body );}}
(3) run the FileLoadClient program in Eclipse to send the request. The running result is as follows:
Printed: succ. jsp page for successful File Upload
Did you find anything similar to the results uploaded on the previous Jsp page? Yes, or the "Request Message Body" after the "Request Header" is removed ".
This method is also very simple. The FileUploadServlet responsible for receiving files has not changed, as long as the file is read to the stream on the client, and then simulate the request servlet.
3. Simulate Post request/Controller (SpringMvc) for File Upload
Finally, the third method is used. The main difficulty is to build the maven + jetty + springmvc environment. The service that receives files is similar to the client that simulates requests.
(1) The FileLoadClient simulating the request has not changed
Import java. io. bufferedReader; import java. io. file; import java. io. inputStream; import java. io. inputStreamReader; import org. apache. commons. httpclient. httpClient; import org. apache. commons. httpclient. httpStatus; import org. apache. commons. httpclient. methods. postMethod; import org. apache. commons. httpclient. methods. multipart. filePart; import org. apache. commons. httpclient. methods. multipart. multipartRequestEnti Ty; import org. apache. commons. httpclient. methods. multipart. part; import org. apache. log4j. logger; public class FileLoadClient {private static Logger logger = Logger. getLogger (FileLoadClient. class); public static String fileload (String url, File file) {String body = "{}"; if (url = null | url. equals ("") {return "parameter illegal";} if (! File. exists () {return "the file name to be uploaded does not exist";} PostMethod postMethod = new PostMethod (url); try {// FilePart: class used to upload files, file: FilePart fp = new FilePart ("file", file); Part [] parts = {fp}; // for MIME-type requests, httpclient we recommend that you use MulitPartRequestEntity to wrap MultipartRequestEntity mre = new multipartreququestentity (parts, postMethod. getParams (); postMethod. setRequestEntity (mre); HttpClient client = new HttpClient (); // Because the file to be uploaded may be large, set the maximum connection timeout value here. getHttpConnectionManager (). getParams (). setConnectionTimeout (50000); int status = client.exe cuteMethod (postMethod); if (status = HttpStatus. SC _ OK) {InputStream inputStream = postMethod. getResponseBodyAsStream (); BufferedReader br = new BufferedReader (new InputStreamReader (inputStream); StringBuffer stringBuffer = new StringBuffer (); String str = ""; wh Ile (str = br. readLine ())! = Null) {stringBuffer. append (str);} body = stringBuffer. toString () ;}else {body = "fail" ;}} catch (Exception e) {logger. warn ("File Upload exception", e) ;}finally {// release the connection postMethod. releaseConnection () ;}return body;} public static void main (String [] args) throws Exception {String body = fileload ("http: // localhost: 8080/fileupload/upload ", new File (" C:/1111.txt"); System. out. println (body );}
(2) Change servlet to Controller in springMvc
Import java. io. file; import java. io. fileOutputStream; import java. io. IOException; import java. io. inputStream; import javax. servlet. http. httpServletRequest; import javax. servlet. http. httpServletResponse; import org. apache. log4j. logger; import org. springframework. stereotype. controller; import org. springframework. web. bind. annotation. requestMapping; import org. springframework. web. bind. annotation. requestMethod ;@ Controller @ RequestMapping ("/fileupload") public class FileUploadService {private Logger logger = Logger. getLogger (FileUploadService. class); @ RequestMapping (consumes = "multipart/form-data", value = "/hello", method = RequestMethod. GET) public void hello (HttpServletRequest request, HttpServletResponse response) throws IOException {response. getWriter (). write ("Hello, jetty server start OK. ") ;}@ RequestMa Pping (consumes = "multipart/form-data", value = "/upload", method = RequestMethod. POST) public void uploadFile (HttpServletRequest request, HttpServletResponse response) throws IOException {String result = ""; if (request. getContentLength ()> 0) {InputStream inputStream = null; FileOutputStream outputStream = null; try {inputStream = request. getInputStream (); // set the time to a new file in milliseconds to prevent the name from being long now = System. curre NtTimeMillis (); File file = new File ("c:/", "file-" + now + ". txt "); file. createNewFile (); outputStream = new FileOutputStream (file); byte temp [] = new byte [1024]; int size =-1; while (size = inputStream. read (temp ))! =-1) {// 1 kb is read each time until outputStream is read. write (temp, 0, size);} logger.info ("File load success. "); result =" File load success. ";} catch (IOException e) {logger. warn ("File load fail. ", e); result =" File load fail. ";} finally {outputStream. close (); inputStream. close () ;}} response. getWriter (). write (result );}}
(3) Start the core code of jetty, right-click in Eclipse to start it, or press the project into jar to start it.
Import org. apache. log4j. logger; import org. eclipse. jetty. server. connector; import org. eclipse. jetty. server. server; import org. eclipse. jetty. server. serverConnector; import org. eclipse. jetty. webapp. webAppContext; public class Launcher {private static Logger logger = Logger. getLogger (Launcher. class); private static final int PORT = 8080; private static final String WEBAPP = "src/main/webapp"; private static final String CONTEXTPATH = "/"; private static final String DESCRIPTOR = "src/main/webapp/WEB-INF/web. xml ";/** create a Jetty Server, specify the port, web directory, root directory, and web path * @ param port * @ param webApp * @ param contextPath * @ param descriptor * @ return Server */public static Server createServer (int port, string webApp, String contextPath, String descriptor) {Server server = new Server (); // set to disable the Jetty hook when JVM exits. // you can enable Jetty once during the entire function test and enable it to automatically disable the server when JVM exits. setStopAtShutdown (true); ServerConnector conne= new ServerConnector (server); connector. setPort (port); // solve the problem that the port conflict is not reported when Jetty is repeatedly started in Windows. // there is a problem with the connector Implementation of Windows + Sun in Windows, when reuseAddress = true, if Jetty starts the same port repeatedly, no error will be reported. // Therefore, it must be set to false. The cost is that if the last exit is not clean (such as TIME_WAIT ), the new Jetty cannot be started, but it should be set as Falseconnector. setReuseAddress (false); server. setConnectors (new Connector [] {connector}); WebAppContext webContext = new WebAppContext (webApp, contextPath); webContext. setDescriptor (descriptor); // sets the webContext location of the webapp. setResourceBase (webApp); webContext. setClassLoader (Thread. currentThread (). getContextClassLoader (); server. setHandler (webContext); return server;}/*** start jetty service **/public void startJetty () {final Server server = Launcher. createServer (PORT, WEBAPP, CONTEXTPATH, DESCRIPTOR); try {server. start (); server. join ();} catch (Exception e) {logger. warn ("failed to start jetty server", e); System. exit (-1) ;}} public static void main (String [] args) {(new Launcher ()). startJetty (); // test url after jetty is started // http: // localhost: 8080/fileupload/hello }}
SpringMvc configuration is not pasted. You can download the source code to see it.
(4) Running Effect
After Launcher is run, you can access http: // localhost: 8080/fileupload/hello to check whether jetty + springMvc is started normally.
Logs printed after FileLoadClient is run:
Indicates that the file is uploaded successfully.
Download with source code:
Jsp_upload-servlet project :( 1). Jsp/servlet implementation file upload (2). Simulate Post request/servlet implementation File Upload
Jetty_upload-springmvc project :( 3). Simulate Post request/Controller (SpringMvc) for File Upload
Csdn
Three methods of File Upload-Java
GitHub
https://github.com/leonzm/jsp_upload-servlet.git
https://github.com/leonzm/jetty_upload-springmvc.git
Time is too short, and there may be something wrong or not perfect. You can come up and learn it together.
Reference:
Analysis of HTTP protocol
Http://www.cnblogs.com/gpcuster/archive/2009/05/25/1488749.html
HTTP protocol details
Http://blog.csdn.net/gueter/article/details/1524447
HTTP protocol details
Http://kb.cnblogs.com/page/130970/
HttpClient Learning
Http://www.cnblogs.com/ITtangtang/p/3968093.html
Differences between TCP/IP, Http, and Socket
Http://jingyan.baidu.com/article/08b6a591e07ecc14a80922f1.html
Spring MVC tutorial, Quick Start, in-depth analysis
Http://yinny.iteye.com/blog/1926799
Jetty startup and embedded startup
Http://yinny.iteye.com/blog/1926799
Jetty Startup Mode
Http://hbiao68.iteye.com/blog/2111007
Jetty is a more practical Bootstrap program
Http://www.xuebuyuan.com/1400368.html