第一次提交表单后无法维护上传的文件

Unable to maintain uploaded file after first form submission

我有一个 p:uploadFile 组件可以上传文件。此外,我还有一个上传按钮,可以上传文件并在一些变量中设置文件名。文件已正确上传并在相应变量中也已正确设置。

问题是当我最终提交整个表单以保存我的所有更改时。此时保存上传文件的变量不再为空,但似乎我的变量中不再有文件,因为文件名及其内容都是空的。

详细。

我的 xhtml 页面:

<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>

我的控制器:

@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(){
        ....
    }

}

我的 TempDTO 包含一个 UploadedFile,如下所示。在我的表单中看到的数据table 显示了一个 TempDTO 列表:

public class TempDTO {
    ...
    ...


    private UploadedFile myUploadedFile;


    public UploadedFile getMyUploadedFile() {
        return myUploadedFile;
    }

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

问题是在以下情况下发现的:

  1. 我 select 一个文件,然后按 table 特定行中的上传按钮。
  2. 在按下上传按钮时在我的控制器中调试 uploadFile 方法显示一切正确并且文件设置正确。在那个阶段我可以看到它的文件大小、文件名等。
  3. 现在我不执行任何其他操作,而是按 "Save" 按钮保存我表单中的所有更改。
  4. 在这个阶段,所有更改都已正确提交,但文件除外。 TempDTO 中的 myUploadedFile 没有文件名,其大小也为零。

我在这个阶段的想法是,当我提交整个表单以保存所有更改时,value="#{currentTableRow.myUploadedFile}" 我在上传组件中替换了每个 table 条目的文件。

更新

我进行了以下更改,但仍然没有成功。

我在我的控制器中添加了一个 UploadedFile,以便在我的 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(){
            ....
        }
    }

同时更新我的​​ uploadFile 组件以指向我的控制器内的 UploadedFile,而不是我的 DTO:

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

不,当我按下 "Save" 按钮并再次提交整个表单并调用 saveAllChanges() 时,myUploadedFile 确实有一个文件名,但是像 getContents()[=54= 这样的方法] 或 getSize() return a java.nio.file.NoSuchFileException 所以我仍然没有文件的内容。

看起来答案是在以下位置找到的:

"另请注意,您应该在上述方法中立即读取文件内容,而不是在稍后的 HTTP 请求调用的不同 bean 方法中读取。这是因为上传的文件内容是请求范围内的,并且因此在 later/different HTTP 请求中不可用。任何在以后的请求中读取它的尝试很可能会在临时文件上以 java.io.FileNotFoundException 结束。"

所以我必须在我的实现中采用变通方法