We have a website running on Tomcat 7.0.27, and we use the following Ajax JavaScript code to dynamically upload an image in our website:
var fileInput = document.getElementById("uploadfile");
var formData = new FormData();
formData.append("uploadfile", fileInput.files[0]);
$.ajax({
url: '<c:url value="/something/PhotoUpload"/>',
type: 'POST',
data: formData,
async: true,
cache: false,
dataType: 'json',
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function(data, textStatus, jqXHR)
{
// do something;
},
error: function(jqXHR, textStatus, errorThrown)
{
// Handle errors here
}
});
The server side is a servlet with the following post method:
@MultipartConfig
public class PhotoUploadAjaxServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part part = request.getPart("uploadfile");
if (part != null) {
//Process image
}
}
}
This all works great, "part" contains our uploaded file. We added the HDIV library to protect against some security vulnerabilities, and now "part" suddenly is null. I cannot figure out why.
The rest of the application uses Struts 1.2.7, and that part is protected by HDIV, but the /PhotoUpload url is not, so HDIV shouldn't touch the request at all. Here is the hdiv-config.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:hdiv="http://www.hdiv.org/schema/hdiv"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.hdiv.org/schema/hdiv http://www.hdiv.org/schema/hdiv/hdiv.xsd">
<hdiv:config errorPage="/InternalError.do" excludedExtensions="css,png,gif,jpeg,jpg,js"
protectedExtensions="/something/*.do, /something/*.action" maxPagesPerSession="20" confidentiality="true"
avoidValidationInUrlsWithoutParams="true" reuseExistingPageInAjaxRequest="true">
<hdiv:sessionExpired homePage="/" />
<hdiv:startPages>/Login.do</hdiv:startPages>
<hdiv:startPages>/LoginSubmit.do</hdiv:startPages>
<hdiv:startPages>/InternalError.do</hdiv:startPages>
<!-- Some things removed to protect the innocent -->
<hdiv:startParameters>org.apache.struts.action.TOKEN,org.apache.struts.taglib.html.TOKEN</hdiv:startParameters>
</hdiv:config>
</beans>
A weird thing I noticed is: when the image uploaded is sufficiently large - e.g. 3MB - the whole thing works again, despite HDIV. "part" contains the file just like it should. In the log I see this:
org.hdiv.config.multipart.StrutsMultipartConfig:79 - Size limit exceeded exception
I therefore think HDIV is somehow misconfigured when the multipart data is stored in memory. Once the size of the data is sufficiently large the data is stored on the file system and then it works.
What am I doing wrong?
Instead of processing that file with a custom servlet, you have to process the file with a Struts action.
You can see an example here.