PrimeFaces p:file上传多个文件自动完成仅在第一个文件后有效

PrimeFaces p:fileUpload multiple files autoComplete only works after first file

本文关键字:文件 第一个 有效 file PrimeFaces      更新时间:2023-09-26

我尝试上传一些文件,然后重定向到另一个页面oncomplete 问题是oncomplete仅在上传第一个文件后才能正常工作

<p:fileUpload  mode="advanced"
     label="#{FileMessages.file_add_file_lbl_Select_File}"
     fileUploadListener="#{fileAddFileAction.upload}"
     oncomplete="redirect(#{fileAddFileAction.groupId});"
     multiple="true"
     allowTypes="/('.|'/)(txt|doc|docx|pdf)$/"
     widgetVar="fileUplaod" >
 </p:fileUpload>

Java 脚本函数:重定向(groupId)

function redirect(groupId) {
     var url = "/network/group/files.html?gId="+groupId;
     $(location).attr('href',url);
}

豆子.java

public void upload(FileUploadEvent event) {
    UploadedFile uploadedFile = event.getFile();
    try {
        String thumbnail = getDestination() + uploadedFile.getFileName();
        String[] filetype = thumbnail.split("''.");
        String newfilename = Calendar.getInstance().getTimeInMillis() + "." + filetype[1];
        SystemFile file = new SystemFile();
        file.setAccount(getActor().getAccount());
        file.setCtime(new Date());
        file.setName(newfilename);
        file.setPath(getDestination());
        file.setFileType(FileUtil.checkFileType(filetype[1]));
        file.setOriginalName(uploadedFile.getFileName());
        getFileService().saveSystemFile(file);
        copyFile(getDestination() + newfilename, uploadedFile.getInputstream());
        copyFile(getDestination() + newfilename, uploadedFile.getInputstream());
    } catch (IOException ex) {
        Logger.getLogger(FileAddFileAction.class.getName()).log(Level.SEVERE, null, ex);
    }
}

似乎是一个已知问题:http://code.google.com/p/primefaces/issues/detail?id=3836

用户在此页面上完成了自定义补丁:

它可以通过在 p:fileUpload 标签中添加以下行来使用:

<p:ajax event="fileUploadsComplete" listener="#{filesBean.done}"/>

其中 filesBean.done 方法如下所示:

public void done(FileUploadsCompleteEvent event) {
    System.out.println("done"); 
}

我也有类似的问题(Primefaces 5)。添加 ajax 文件上载完成失败,原因是"父级不是客户端行为持有者的实例"错误。

这是我的黑客。这不是最令人满意的,但它正在工作:

<script>
    function setUploadFilesCount() {
        var numberOfFiles = $('.ui-fileupload-preview').size();
        var input = document.getElementById('fileupload-multi-fix-input');
        input.value = numberOfFiles;
        input.onchange();
    }
</script>
<h:form id="file-upload-form">
    <p:fileUpload id="file-upload" fileUploadListener="#{backingBean.handleFilesUpload}" mode="advanced" dragDropSupport="false"
                               sizeLimit="10000000" multiple="true" allowTypes="/('.|'/)(jpg)$/" onstart="setUploadFilesCount()" update=":content">
    </p:fileUpload>
</h:form>
<h:form prependId="false" style="display:none;">
    <h:inputText id="fileupload-multi-fix-input" value="#{backingBean.numberOfUploadFiles}">
        <f:ajax event="change" execute="@form"  />
    </h:inputText>
</h:form>

所以在我的背豆中,我有以下内容:

@Named
@SessionScoped
public class BackingBean implements Serializable{
    private static final long serialVersionUID = 1L;
    private int numberOfUploadFiles; //... add getter and setter
    private boolean isUploadComplete = false; //... add getter and setter
    private int uploadCount = 0;
    public void handleFilesUpload(FileUploadEvent event) throws IOException {
        // ... handle file upload here
        uploadCount++;
        if(uploadCount == numberOfUploadFiles){
            isUploadComplete = true;
        }
    }
}

解释:

我添加了一个 JavaScript 函数setUploadFilesCount和第二个包含隐藏<h:input /><h:form />

<p:fileUpload onstart=...在(第一次)文件传输开始时调用一次。我在 onstart 中调用 JavaScript 函数setUploadFilesCount来设置我的后备 Bean 中的上传文件数量。

通过读取带有 css 类 ui-fileupload-preview 的元素的出现次数来检测文件数。视图中ui-fileupload-preview元素的数量等于上传文件的数量。这发生在

$('.ui-fileupload-preview').size();

input.onchange();会导致将隐藏的输入字段值提交到后备 Bean。

在支持Bean上,我可以通过增加计数器来检查最后一项是否已上传

uploadCount++;
if(uploadCount == numberOfUploadFiles){...}

所以我可以检查是否所有项目都已上传或在最后一个上传项目完成后调用特殊函数。


每次上传其中一个

上传文件时都会调用<p:fileUpload oncomplete...

因此,在您的特定情况下,您必须将javascript另外包装成这样的东西:

<h:panelGroup id="afterLoad">
    <h:outputScript>
        function redirect(groupId) {
            if(#{backingBean.isUploadComplete}=='true'){
                var url = "/network/group/files.html?gId="+groupId;
                $(location).attr('href',url);
            }
        }
    </h:outputScript>
</h:panelGroup>

将其与<p:fileUpload相同的形式放置并添加<p:fileUpload ... update="afterLoad" ...