It appears that you don't exactly realize that JSF is in the context of this question merely a HTML code generator. JSF offers a <h:inputFile>
component which generates a HTML <input type="file">
element.
Try it yourself:
<h:form id="uploadForm" enctype="multipart/form-data">
<h:inputFile id="file" value="#{bean.file}" />
<h:commandButton id="submit" value="submit" />
</h:form>
If you open the JSF page in a webbrowser and do rightclick and View Page Source, then you should see something like this:
<form id="uploadForm" name="uploadForm" method="post" action="/playground/test.xhtml" enctype="multipart/form-data">
<input type="hidden" name="uploadForm" value="uploadForm" />
<input id="uploadForm:file" type="file" name="uploadForm:file" />
<input type="submit" name="uploadForm:submit" value="submit" />
<input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="3646344859491704387:-5449990057208847169" autocomplete="off" />
</form>
Look, there is your <input type="file">
element!
Now, if we configure Dropzone as per its documentation (and you install the dropzone.js
file in your JSF project as per the instructions in How to reference CSS / JS / image resource in Facelets template?), then we should end up in the JSF page with something like this:
<h:head>
...
<h:outputScript name="dropzone.js" />
<h:outputScript>Dropzone.options.uploadForm = { paramName: "uploadForm:file" };</h:outputScript>
</h:head>
<h:body>
<h:form id="uploadForm" enctype="multipart/form-data" styleClass="dropzone">
<div class="fallback">
<h:inputFile id="file" value="#{bean.file}" />
<h:commandButton id="submit" value="submit" />
</div>
</h:form>
</h:body>
The bean looks just like this:
@Named
@RequestScoped
public class Bean {
private Part file;
public void save() throws IOException {
String fileName = file.getSubmittedFileName();
String contentType = file.getContentType();
long size = file.getSize();
InputStream content = file.getInputStream();
// ...
}
public Part getFile() {
return file;
}
public void setFile(Part file) throws IOException {
this.file = file;
save();
}
}
There are 3 things to take into account with JSF:
- The Dropzone
paramName
option must be set to exactly the name
of the generated <input type="file">
element, which is uploadForm:file
in the above example.
- The JSF input file and command button components must be wrapped in an element with Dropzone-specific
class="fallback"
in order to be hidden (and provide a fallback for JavaScript/Ajax-deficient clients). Do not remove them, otherwise JSF will refuse to process the uploaded file, because it needs to perform its job based on the component tree.
- The
save()
method is invoked directly by the setter. This is kind of fishy, but as Dropzone doesn't offer an opportunity to directly trigger a backing bean action method, this is the easiest workaround. Another workaround is to attach a valueChangeListener
on the <h:inputFile>
and queue the event to the INVOKE_APPLICATION
phase as per How to get updated model values in a valueChangeListener method?
Your next question shall probably be "How should I save it?". In that case, continue here:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…