在ui:repeat中上传JSF文件

3
我有一个UI,其中有选项可以上传多个特定类型的文档到一个问题中。在我的应用程序其余部分中,我能够上传单个文件而没有任何问题。
环境:
- Tomcat 7.0.x - Mojarra JSF实现2.1.3(20110908-FCS) - 带有Primefaces 2.2的JSF 2.1 - Apache Tomahawk
代码解释:
以下是循环遍历文档信息实体的代码。这些实体要么是来自数据库的记录,要么是占位符。如果它存在,则实体将具有指向数据库中该项的ID,否则它将为0,表示它是一个占位符,可以上传文件。
在占位符情况下,有一个上传按钮,它会带出一个Primefaces对话框,其中包含了一个Tomahawk文件上传组件。
代码:
以下是JSF代码:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core">

<ui:repeat var="extDoc" value="#{reportBean.externalDocs}"
        varStatus="extDocIdx">
    <!-- Display the document name -->
    <h:outputText value="#{extDoc.name}"/>

    <!-- if the document is not in the database, give the option to add it -->
    <ui:fragment rendered="#{extDoc.id == 0}">
        <!-- On click of the upload button, display the dialog -->
        <h:commandButton value="Upload" type="button"
            onclick="uploadDlg#{extDocIdx.index}.show()" modal="true"/>

        <p:dialog header='Upload document for #{extDoc.name}'
                modal="true" widgetVar="uploadDlg#{extDocIdx.index}"
                width="650" minWidth="650">
            Select the file to upload:
            <!-- THIS IS WHERE THE PROBLEM IS -->
            <t:inputFileUpload value="#{reportBean.uploadedFile}"/>
            <br/>
            <h:commandButton value="Submit"
                action="#{reportBean.addExtDocument(extDoc.name, extDocIdx.index)}"/>
        </p:dialog>
    </ui:fragment>

    <ui:fragment rendered="#{extDoc.id != 0}">
        <!-- display a link to the uploaded file -->
    </ui:fragment>
</ui:repeat>

报告Bean中的uploadedFile属性:
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() { return uploadedFile; }
public void setUploadedFile(UploadedFile value) { uploadedFile = value; }

public void addExtDocument(String name, int idx)
    throws IOException
{
    // access uploadedFile to persist the information
}

问题

我犯了一个错误,只有一个uploadedFile变量来处理上传文件的整个循环;因此循环中的最后一项总是会覆盖其他项,使得除了最后一项之外的任何项都无法上传。显然,我需要为每次循环指定不同的uploadedFile。我尝试过使用List<UploadedFile>,但不清楚如何初始化数组,以及t:inputFileUpload组件如何在提交时更新值。

问题

所以问题是:我应该在t:inputFileUpload中包含什么样的EL,在ReportBean中使用什么样的属性来使我的addDocument方法中有可用的单独的uploadedFile实例?

1个回答

5
您可以使用 List<UploadedFile>UploadedFile[],并使用大括号标记访问单个项目,在其中传递当前 <ui:repeat> 的索引,如下所示:
<t:inputFileUpload value="#{reportBean.uploadedFiles[extDocIdx.index]}"/>

无论哪种方式,您都需要确保属性已正确预初始化。 List 必须使用 new ArrayList<>() 进行初始化,并且数组必须预先初始化为完全正确的长度。JSF/EL 不会为您预创建它;它仅仅将给定的项目设置在给定的索引上,就是这样。对于空列表或数组,您只会遇到 PropertyNotWritableException,而对于空数组或错误大小的数组,您只会遇到 ArrayIndexOutOfBoundsException

第一次尝试的结果是:javax.servlet.ServletException: IterationStatus{index=0, first=true, last=false, begin=null, end=null, step=null, even=true, current=null, iterationCount=0}仍在研究中。 - Pixel
你应该传递 extDocIdx.index,而不是 extDocIdx。我宁愿将 extDocIdx 重命名为更具自说明性的 loopiteration。因为它实际上并不代表索引,而只是循环/迭代状态,其中又有几个获取器 getIndex()isFirst()isLast()getBegin() 等。 - BalusC
1
没错,就是这样!15欧元已通过PayPal发送以示感谢。 - Pixel
我也按照你建议将变量名"extDocIdx"改为包含"loop",而不是"Idx"。同意,这样更明显。 - Pixel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接