第一次提交表单后无法维护上传的文件
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;
}
}
问题是在以下情况下发现的:
- 我 select 一个文件,然后按 table 特定行中的上传按钮。
- 在按下上传按钮时在我的控制器中调试 uploadFile 方法显示一切正确并且文件设置正确。在那个阶段我可以看到它的文件大小、文件名等。
- 现在我不执行任何其他操作,而是按 "Save" 按钮保存我表单中的所有更改。
- 在这个阶段,所有更改都已正确提交,但文件除外。 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 结束。"
所以我必须在我的实现中采用变通方法
我有一个 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;
}
}
问题是在以下情况下发现的:
- 我 select 一个文件,然后按 table 特定行中的上传按钮。
- 在按下上传按钮时在我的控制器中调试 uploadFile 方法显示一切正确并且文件设置正确。在那个阶段我可以看到它的文件大小、文件名等。
- 现在我不执行任何其他操作,而是按 "Save" 按钮保存我表单中的所有更改。
- 在这个阶段,所有更改都已正确提交,但文件除外。 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 结束。"
所以我必须在我的实现中采用变通方法