I know how to do file upload using Primefaces or using Tomahawk, however, I am trying to doing file upload using Apache Commons FileUpload and so far I am having a bit of road block. Even though my form use multipart/form-data
, when I submit my form, the content type become application/x-www-form-urlencoded
. Here is my code
<h:body>
<h:form enctype="multipart/form-data">
Upload File
<input type="file" name="file"/>
<p:commandButton value="Submit" action="#{viewBean.submit}"/>
</h:form>
</h:body>
Here is my ViewBean
@ManagedBean
@ViewScoped
public class ViewBean implements Serializable {
public void submit() {
String url = "/FileUploadServlet";
FacesContext context = FacesContext.getCurrentInstance();
try {
String contentType = context.getExternalContext().getRequestContentType();
context.getExternalContext().dispatch(url);
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception when calling Servlet", e);
} finally {
context.responseComplete();
}
}
}
So when I try to print the content type above, it showed application/x-www-form-urlencoded
. If I put ajax="false"
to my p:commandButton
, then the submit()
method is not even invoked, but if I take out enctype="multipart/form-data"
(still keep ajax="false"
), then submit()
is invoked but it is not multipart, it is application/x-www-form-urlencoded
, so apache commons fileupload throw an exception since it is not multipart. Seems like whatever I do, I cant seems to get the multipart requrest. Please help
The
<p:commandButton>
sends by default an ajax request of level 1XMLHttpRequest
. This does not supportmultipart/form-data
. Only level 2XMLHttpRequest
supports it, but it's only supported in the newest browsers (those also supporting HTML5) and not implemented in JSF JS API nor in PrimeFaces JS API.This way however a fullworthy
multipart/form-data
will be sent. That the submit method is not invoked is just because JSF prior to version 2.2 does not supportmultipart/form-data
requests out the box. JSF collects the submitted data by default usingrequest.getParameter()
andgetParameterMap()
on the underlying HTTP servlet request. However, this will returnnull
when an encoding other thanapplication/x-www-form-urlencoded
is been used. As JSF determines the to-be-invoked action method based on submitted data, it won't be able to locate and invoke it when the data isnull
.In theory, if you create a
Filter
which uses Apache Commons FileUpload or the new Servlet 3.0request.getPart()
/getParts()
methods to extract the data from themultipart/form-data
request and wraps the current HTTP servlet request with a custom implementation which overrides thegetParameter()
calls wherein a mapping of the extracted data is been supplied, then JSF will be able to do the needed job based on results ofgetParameter()
calls. You can find a concrete example utilizing the Servlet 3.0 API in this article and the same example which is slightly changed to utilize Apache Commons FileUpload in this answer.The upcoming JSF 2.2 will have a new
<h:inputFile>
component which is bindable to a Servlet 3.0Part
property.with
JSF 2.2 final release is scheduled for late end of Q1, but is currently available as a snapshot release.