In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly analyzes the Struts2 upload file how to understand the relevant knowledge points, the content is detailed and easy to understand, the operation details are reasonable, and has a certain reference value. If you are interested, you might as well follow the editor to have a look, and follow the editor to learn more about "how to understand Struts2 uploaded files".
By default, the bottom layer of the Struts2 framework uses the commons-fileupload component of apache to accept and process uploaded files.
When the file size is limited by the struts.multipart.maxSize attribute, it will directly affect the file size setting of the commons-fileupload component, which defaults to 2m. When the uploaded file exceeds this size, a SizeLimitExceededException exception is thrown from the commons-fileupload component. After the Struts2 upload file interceptor catches this exception, it will directly set the exception message to an error message at the Action level.
After my testing and the Debug of the source code, I found that, as Sun Xin said in the book, if the uploaded file is greater than 2m, there will be a lot of English error messages on the page, roughly as follows: the request was rejected because its size....exceeds the configured maximum... And the error message from the MultiPartRequestWrapper type request object is added to the Action error in fieUpload.
At this point, the error message that your custom upload file is too large in ApplicationResources.properties doesn't work at all. The reason is that, as stated in the book, exceptions are thrown in the underlying commons-fileupload components and the file is not uploaded at all, so when it comes to the fileUpload interceptor, it is impossible to judge the type and size of the file based on the fact that the file cannot be obtained.
However, this exception directly raises two problems:
1. An error message in English is displayed on the page. This kind of information is obviously not what we want.
2. Due to the error, other text input on the original page is also missing, that is to say, params injection failed.
With these two questions in mind, let's explore how Struts2 handles requests.
Note: this is not an introduction to the Struts2 request process, but a simple analysis to solve the above two problems.
First of all, of course, we have to operate on FilterDispatcher.
The prepareDispatcherAndWrapRequest method is called in the doFilter method, and in order to wrap Struts2's own request object, the wrapRequest method of the Dispatcher class is called in the prepareDispatcherAndWrapRequest method, in which it is decided whether to use the HttpServletRequestWrapper class of tomcat to separate the data in the request or the MultiPartRequestWrapper of Struts2 to separate the data in the request, depending on the type of content of the request (whether it is submitted in text or multipart/form-data format).
Note: when you request to the server, the data is submitted to the server in the form of a stream, and the content is something with rules. When we usually use the request built-in object to get parameter in jsp, it is actually decomposed by the HttpServletRequestWrapper class of tomcat, so there is no need for us to decompose these things.
Of course, here we are looking at uploading files, so because the submission set in form is in media format, the wrapRequest method of the Dispatcher class passes the request to the MultiPartRequestWrapper class.
MultiPartRequestWrapper is the class of Struts2 and inherits the HttpServletRequestWrapper class of tomcat. It is also the class that we will use to replace the class of HttpServletRequest. As you can see from the name, it is a wrapper class for multimedia requests.
Instead of creating a new wheel to parse the request, Struts2 itself leaves it to the commons-fileupload component of Apache to parse.
In the constructor of MultiPartRequestWrapper, the parse method of MultiPartRequest (the default is the JakartaMultiPartRequest class) is called to parse the request.
Only in the parse method of the JakartaMultiPartRequest class of Struts2 will the ServletFileUpload class of the commons-fileupload component be called to parse the request. At this point, Struts2 has implemented the whole process of transferring the request to the commons-fileupload component to parse the request. The rest is to wait for the commons-fileupload component to parse the request, get the decomposed data, and then put the decomposed field name and value into params (HashMap type) according to the field name. At the same time, the JakartaMultiPartRequest class resets many HttpServletRequest methods, such as getParameter, getParameterNames, and getParameterValues, which actually take the data from the parsed params object. In this process, the commons-fileupload component obediently analyzes the uploaded file. JakartaMultiPartRequest also impolitely put the decomposed files one by one into files (HashMap type). In fact, at this time, the commons-fileupload component has already uploaded all the files to be uploaded.
At this point, Struts2 has implemented the wrapper for the HttpServletRequest class, and when you get back to the MultiPartRequestWrapper class, take the error that occurred in the above parsing process, and then add the error to its own errors list. Similarly, we will find that in the MultiPartRequestWrapper class, many methods of the HttpServletRequest class are overloaded, after all, it is a wrapper class. In fact, for the request to upload files, the request used in the later processing of Struts2 are all MultiPartRequestWrapper class objects. For example, when we call getParameter, we directly call the getParameter method of MultiPartRequestWrapper and indirectly call the getParameter method of the JakartaMultiPartRequest class object.
Note: from here, we can see that JakartaMultiPartRequest is completely designed as a replaceable class.
Then we go back to the wrapRequest method of the Dispatcher class, and we return the MultiPartRequestWrapper object directly, and we finally return to the prepareDispatcherAndWrapRequest method of the FilterDispatcher class. At this point, we get the fully parsed request object (MultiPartRequestWrapper class), which is further returned to the doFilter method of the FilterDispatcher class, that is, back to the starting point. At this point, the request object obtained in doFilter is a HttpServletRequest object that decomposes the data in the request. We can use the getParameter method to get the data, at the same time, we can also use getFiles to get the file array.
In the doFilter method, the getMapping method of actionMapper is further called to parse the url to find out the namespace and action name for later use by calling the corresponding interceptor and action according to the configuration file.
The next call to the serviceAction method of the Dispatcher class in the doFilter method is no longer described. In short, before action is called, it will first go to the fileUpload interceptor (corresponding to the FileUploadInterceptor class). In this interceptor, it will first check whether request is MultiPartRequestWrapper. If not, it means that the request,fildUpload interceptor that is not used to upload the file will directly hand over the control to the next interceptor. If so, the request object will be forcefully converted into a MultiPartRequestWrapper object, and then the hasErrors method will be called to see if there are any upload errors, and if so, it will be directly added to the Action error (Action level).
In addition, the fileUpload interceptor will take out all the files placed in the MultiPartRequestWrapper object, take out the file, file name, file type, and put it into the parameters of request, so that when it comes to the params interceptor, you can easily inject these contents into the Action, which is why the fileUpload interceptor needs to be placed in front of the params interceptor. After the files are placed in the parameters object of request, the fileUpload interceptor will continue to call other interceptors until the execution of Action is complete, and he has to do a clean-up work: delete the files in the temporary folder (these files are uploaded by the commons-fileupload component for you to copy the files in your own Action to the specified directory, when the action execution is finished, these temporary files are of course useless).
Hello, are you still watching? Oh, is it too much, too messy, there is no way, Struts2 is called like this. I don't know if Struts2 has released its Sequence diagram. I want to draw one, but I'm too lazy, so I'd better look at the code and say it.
If you get tired of looking at the top, you can stop looking and just look at the one below.
After the above analysis, the whole process of file upload is over.
Let's get back to our problem.
Let's take a look at * first:
1. An error message in English is displayed on the page. This is obviously not what we want.
There is no way. The commons-fileupload component did not think of internationalization, and in the FileUploadInterceptor interceptor, it did not think about internationalization, and put it directly into the error of Action. There are three ways:
(1) it should be easy to replace this error before the error is displayed. I won't leave it to you to do it.
(2) or rewrite the JakartaMultiPartRequest class to replace the captured exception information with your own, and then replace the parser we rewrote with your own through the Struts2 configuration file.
(3) directly change the class of the commons-fileupload component to Chinese.
Let me talk a little bit about (3): find the FileUploadBase class and change lines 902-908.
FileUploadException ex =
New SizeLimitExceededException (
"the request was rejected because"
+ "its size (" + pCount)
+ ") exceeds the configured maximum"
+ "(" + pSizeMax + ")"
PCount, pSizeMax)
= >
FileUploadException ex = new SizeLimitExceededException (
"the server rejected your request, possibly because the data submitted to the server was lost." , pCount, pSizeMax)
Change lines 914 ~ 918.
Throw new SizeLimitExceededException (
"the request was rejected because its size ("
+ requestSize
+ ") exceeds the configured maximum ("
+ sizeMax + ")"
= >
Throw new SizeLimitExceededException ("the server rejected your request because the amount of data submitted is too large (usually because the uploaded file is too large), please return to the previous page and try again."
+ "(* * bytes:" + sizeMax / 1024
+ "K)", requestSize, sizeMax)
Let's take a look at the second question.
2. Due to the error, all the input on the original page is gone, that is to say, params injection failed.
I found an article on javaeye on this issue (the jar package of the commons-fileupload component used seems old).
Http://www.javaeye.com/topic/197345
Although according to this article, when the upload fails, other inputs can be displayed, but the result is that all files will definitely be uploaded to the server, that is, although the page reports the file because it is too large and the request is rejected, the file will still be uploaded to the server, and the commons-fileupload component will not block the upload of the file at all.
To make it clear here, if you do not throw this exception, the requested stream will continue to be uploaded to the server, and only after the entire stream has been uploaded can the commons-fileupload component correctly analyze the file part and the text part. Therefore, it is a last resort to throw an exception here. If you do not throw an exception, the result is that although the page reports an error, the file will still be uploaded to the server. This step does not block the upload of the input stream at all. If it is not blocked, what will be the consequences?
So, to sum up, for the second problem, if there is this exception, we simply can not make the original input still show, because the commons-fileupload component does not parse all the input content, directly give the exception, to the params interceptor, the request is empty, there is no way to get parameter, so it cannot be injected into Action. In this case, there can only be an error message informing the user that the server rejected the request due to the large amount of data submitted. A better way is to jump directly to a special page, prompt the user, and then let the user click back and enter it again. Otherwise, the user will feel that the uploaded file is big, and even some other contents I entered have not been saved. Of course, if you can upload files with Ajax, it may be a great experience for customers, but this may result in some empty files on the server (which have never been used since upload) that need to be cleared.
After the whole analysis, we say that the second problem is basically unavoidable.
About "how to understand Struts2 upload files" is introduced here, more related content can search previous articles, hope to help you answer questions, please support the website!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.