1

I have a p:uploadFile component in order to upload a file. In addition i have an upload button that does upload the file and is sets in some variables the filename. The file is uploaded correctly and set also correctly in the corresponding variable.

The problem is when i finally submit the entire form to save all my changes. At this point the variable holding the uploaded file, is not null anymore, but it seems that the there is no file anymore in my variable since the filename is empty as also its content.

In detail.

My xhtml page:

<h:form name="myUploadForm" enctype="multipart/form-data">
    <p:commandButton  action="#{controller.saveAllChanges}" value="Save" ajax="false" />


    <p:dataTable....>
        <p:column ... var="currentTableRow">
            <p:commandButton value="Upload" ajax="false" title="#{msg.upload}"
                action="#{controller.uploadFile(currentTableRow)}"
                update=":table" />

            <p:fileUpload id="upload" value="#{currentTableRow.myUploadedFile}" mode="simple"
                skinSimple="true" label="Browse" auto="true" />
        </column>
    </p:dataTable>
</h:form>

My controller:

@ManagedBean
@ViewScoped
public class Controller implements Serializable {
    ...
    public void uploadFile(TempDTO selectedDTO) {
        FacesContext context = FacesContext.getCurrentInstance();

        if (selectedDTO.getMyUploadedFile() != null && selectedDTO.getMyUploadedFile().getSize() > 0) {
            ... 
        } 
    }

    public saveAllChanges(){
        ....
    }

}

My TempDTO contains an UploadedFile as seen below. The datatable seen in my form displays a list of TempDTOs:

public class TempDTO {
    ...
    ...


    private UploadedFile myUploadedFile;


    public UploadedFile getMyUploadedFile() {
        return myUploadedFile;
    }

    public void setMyUploadedFile(UploadedFile myUploadedFile) {
        this.myUploadedFile = myUploadedFile;
    }
}

The problem is noticed when:

  1. I select a file and press the upload button in a specific row of the table.
  2. Debugging the uploadFile method in my Controller when pressing the upload button shows that everything is correct and that the file is correctly set. At that stage i can see its filesize, filename etc.
  3. Now without performing any other action in between i press the "Save" button to save all changes in my form.
  4. At this stage all changes are submitted correct except of the file. The myUploadedFile inside the TempDTO has no filename as also its size is zero.

My thought at this stage was that when i submit the entire form in order to save all changes, the value="#{currentTableRow.myUploadedFile}" i have in the upload component replaces the file for each table entry.

UPDATE

I made following changes but i still had no luck .

I added an UploadedFile inside my controller in order to manually set the uploaded file inside my TempDTO:

@ManagedBean
@ViewScoped

    public class Controller implements Serializable {

        private UploadedFile myUploadedFile;

        public UploadedFile getMyUploadedFile() {
            return myUploadedFile;
        }

        public void setMyTemplateFile(UploadedFile myUploadedFile) {
            this.myUploadedFile = myUploadedFile;
        }

        public void uploadFile(TempDTO selectedDTO) {
            FacesContext context = FacesContext.getCurrentInstance();
            selectedDTO.setTemplateFile(myUploadedFile);
            if (selectedDTO.getMyUploadedFile() != null && selectedDTO.getMyUploadedFile().getSize() > 0) {
                ... 
            } 
        }

        public saveAllChanges(){
            ....
        }
    }

Also update my uploadFile component to point to the UploadedFile inside my controller and not in my DTO:

<p:fileUpload id="upload" value="#{controller.myUploadedFile}" mode="simple"
                    skinSimple="true" label="Browse" auto="true" />

No when i press on the "Save" button and submit the entire form again and call saveAllChanges() , myUploadedFile has indeed a filename , but methods like getContents() or getSize() return a java.nio.file.NoSuchFileException so i still do not have the content of the file.

Stephan
  • 696
  • 15
  • 37
  • 1
    Always directly after uploading the file do something with it. E.g. copy it to an explicit location (even if it is temporary) and use/keep that file reference. You should not 'rely' on the underlying upload solution. – Kukeltje Jul 13 '17 at 10:50
  • Duplicate? https://stackoverflow.com/questions/8875818/how-to-use-primefaces-pfileupload-listener-method-is-never-invoked-or-uploaded – Kukeltje Jul 13 '17 at 11:03
  • 1
    But i do not want to store the file in the file system right after i upload it. I want to store the file on the file system when the user saves all the changes. .Storing the file in file system right after the upload can cause problems. What happens if the the user closes the browser ? I have a junk file in my file system. There should be something for this. – Stephan Jul 13 '17 at 11:17
  • Also, i do not see how my question is related to the one you posted. I did not mention that a listener or a method is not invoked. – Stephan Jul 13 '17 at 11:26
  • 1
    It **is** in the filesystem (for larger files) after the user uploads the file. If you want it to stay somewhere until the user presses save you have the same problem if the user does not press save. Solutions: Either just don't upload it until the user presses the save button, or keep track of the uploaded **and copied** files in a viewscoped bean and remove the non-saved files on pre-destroy. Components/frameworks cannot solve every usecase. And **please** read the 'duplicate' answer fully, not just the html title. The 'copy directly' part I mention (and the reason) is all in there. – Kukeltje Jul 13 '17 at 11:45
  • Possible duplicate of [How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null](https://stackoverflow.com/questions/8875818/how-to-use-primefaces-pfileupload-listener-method-is-never-invoked-or-uploaded) – Kukeltje Jul 13 '17 at 11:45
  • You explain that this is duplicate cause of the sentence: Also note that you should read the file contents immediately inside the abovementioned methods and not in a different bean method invoked by a later HTTP request. This is because the uploaded file contents is request scoped and thus unavailable in a later/different HTTP request. Any attempt to read it in a later request will most likely end up with java.io.FileNotFoundException Please let me know if this is what you mean that could be a possible answer to my question. – Stephan Jul 13 '17 at 11:51
  • Yes it is (or the nio version of the `java.io.FileNotFoundException` in your case) – Kukeltje Jul 13 '17 at 11:54

1 Answers1

0

It looks that the answer is the following one found in: https://stackoverflow.com/a/8880083/1918516

"Also note that you should read the file contents immediately inside the abovementioned methods and not in a different bean method invoked by a later HTTP request. This is because the uploaded file contents is request scoped and thus unavailable in a later/different HTTP request. Any attempt to read it in a later request will most likely end up with java.io.FileNotFoundException on the temporary file."

So i have to go with a workaround in my implementation

Stephan
  • 696
  • 15
  • 37