Summary: Use <h:inputFile />
, at least I couldn't get <rich:fileUpload>
to work in JSF-2.2
Long version:
After spending a day messing around with <rich:fileUpload>
I came to the conclusion that servlet containers adhering to the Servlet-3.0 spec are left between a rock and a hard place here.
What seems to be happening is that Tomcat (or any servlet container implementing Servlet-3.0 and above - I tried with Wildfly's undertow) makes multipart POST submits available via the HttpServletRequest#getParts() method. It also parses the form data nicely and makes it available via ServletRequest#getParameter, which explicitly states:
If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method.
Which is exactly what MultipartRequest25
does if you call it's getParameter
method with a non-existing parameter name:
String parameter = super.getParameter(name);
if (parameter != null) {
return parameter;
}
parseIfNecessary();
The parseIfNecessary()
part tries to read the prolog, but since the container already has parsed the request body the stream is empty and reading from it produces an immediate EOF
which is translated to the IOException
we're seeing.
From the class naming I get the idea that this was written for Servlet-2.5 containers where this probably worked and the info wasn't readily available.
At this point, I decided to leverage my use of JSF-2.2 and switch to h:inputFile which works splendid when you use the latest (at this time of writing) Mojarra-2.2.5 (haven't tried Myfaces).
Here's an example:
<h:form id="fileUploadForm" enctype="multipart/form-data">
<h:inputFile value="#{docMgr.file}" required="true">
<f:ajax listener="#{docMgr.saveFile}" render="@form" />
</h:inputFile>
<h:messages />
</h:form>
Note that versions before Mojarra-2.2.5 had issues with ajax submits like in the example above (which mimicks RichFaces' immediateUpload
.