使用额外的 inputText 上传多个文件 [英] Multiple file upload with extra inputText

查看:17
本文介绍了使用额外的 inputText 上传多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要实现以下内容:

  1. ajax 样式的多个文件上传(无需刷新整个页面)
  2. 每个文件的描述字段
  3. 必须使用 JSF 2.0 来完成

以任意组合执行 3 个要求中的 2 个是没有问题的.Multiple fileUpload with JSF 2.0 = PrimeFaces,JSF 2.2 可以实现多文件上传 + 描述,因为它具有本机上传元素(我猜它可以被 ajaxed 但没有检查它,因为我不能使用它),但是当我得到这三个要求加在一起我就卡住了.在 PrimeFaces 的 p:fileUpload 上没有描述字段,其简单模式不支持 ajax.JSF 2.0 没有原生的 fileUpload 组件.我可以将描述字段与 PrimeFaces 的 p:fileUpload 绑定,但我无法阻止用户选择多个文件,这会导致很少有文件与一个描述相关联.

那么,是否可以在 PrimeFaces 和 JSF 2.0 中以 ajax 样式进行多文件上传和描述字段?

解决方案

PrimeFaces 上传基于 :

.append('<td class=title"><label>Title: <input name=title['+ file.name +']"></label></td>')//我们唯一要做的修改

额外的输入文本称为title[fileName],在这种情况下,您将通过当前文件名获取请求参数的值.

public void handleFileUpload(FileUploadEvent event) {FacesContext 上下文 = FacesContext.getCurrentInstance();Map map = context.getExternalContext().getRequestParameterMap();String paramName = "title["+event.getFile().getFileName()+"]";String fileWithTitle = (String) map.get(paramName);}

这是 add 选项的完整实现(假设您的 widgetVarfileUpload)

$(document).ready(function() {设置超时(文件上传,1000);})函数文件上传(){PF('文件上传').jq.fileupload({添加:函数(e,数据){$this = PF('文件上传');$this.chooseButton.removeClass('ui-state-hover ui-state-focus');如果($this.files.length === 0){$this.enableButton($this.uploadButton);$this.enableButton($this.cancelButton);}如果 ($this.cfg.fileLimit && ($this.uploadedFileCount + $this.files.length + 1) > $this.cfg.fileLimit) {$this.clearMessages();$this.showMessage({摘要:$this.cfg.fileLimitMessage});返回;}var 文件 = data.files ?数据文件[0]:空;如果(文件){var validMsg = $this.validate(file);如果(有效消息){$this.showMessage({摘要:validMsg,文件名:文件名,文件大小:文件大小});}别的 {$this.clearMessages();//我们唯一要做的修改var row = $('<tr></tr>').append('<td class=ui-fileupload-preview"></td>').append('<td>' + file.name + '</td>').append('<td class="title"><label>Title: <input name="title['+ file.name +']"></label></td>').append('<td>' + $this.formatSize(file.size) + '</td>').append('').append('<td><button class="ui-fileupload-cancel ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only"<span class=ui-button-icon-left ui-icon ui-icon ui-icon-close"></span><span class=ui-button-text">ui-button</span></button></td>').appendTo($this.filesTbody);if ($this.isCanvasSupported() && window.File && window.FileReader && $this.IMAGE_TYPES.test(file.name)) {var imageCanvas = $('<canvas></canvas').appendTo(row.children('td.ui-fileupload-preview')),context = imageCanvas.get(0).getContext('2d'),winURL = window.URL ||window.webkitURL,url = winURL.createObjectURL(file),img = 新图片();img.onload = 函数(){var imgWidth = null, imgHeight = null, scale = 1;如果 ($this.cfg.previewWidth > this.width) {imgWidth = this.width;}别的 {imgWidth = $this.cfg.previewWidth;比例 = $this.cfg.previewWidth/this.width;}var imgHeight = parseInt(this.height * scale);imageCanvas.attr({width: imgWidth, height: imgHeight});context.drawImage(img, 0, 0, imgWidth, imgHeight);}img.src = url;}//进步row.children('td.ui-fileupload-progress').append('<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin=0" aria-valuemax=100" aria-valuenow=0">

只是将上面的代码包含在一些js文件中,并在</h:body>

结束之前包含它

这是一个在线演示.>

注意:如果用户选择了多个具有完全相同的名称和扩展名的文件,您可能在这种方法中唯一的拖动你会得到两次第一个标题!,对于某些人来说这没问题,因为用户不应该上传相同的文件.

这是在 PrimeFaces 5.0 和 Chrome 上的测试.

I need to implement the following:

  1. multiple file upload in ajax style (without refreshing whole page)
  2. description field per file
  3. it must be done with JSF 2.0

There isn't problem to do 2 of 3 requirement in any combination. Multiple fileUpload with JSF 2.0 = PrimeFaces, multiple file upload + description is possible with JSF 2.2 because it has native upload element (I guess it can be ajaxed but didn't check it because I can't use it), but when I get all three requirements together I get stuck. On PrimeFaces's p:fileUpload there isn't description field and its simple mode doesn't support ajax. JSF 2.0 doesn't have native fileUpload component. I can bind description field with PrimeFaces's p:fileUpload but I can't prevent from a user to choose multiple files and it cause that few files will be tied to one description.

So, is it possible to do multiple file upload in ajax style with description field in PrimeFaces and JSF 2.0?

解决方案

PrimeFaces upload is based on blueimp/jQuery-File-Upload.

When .serializeArray() gets called, all the data inside that form would be serialized.

In that case you could override the PrimeFaces implementation of the add option to append one extra input text for each file.

So the result would look like this:

Now that would be one extra line of code, exactly here:

.append('<td class="title"><label>Title: <input name="title['+ file.name +']"></label></td>') //the only modification we have to do

The extra input text is called title[fileName], in that case you would get the value of the request parameter by the current file name.

public void handleFileUpload(FileUploadEvent event) {
    FacesContext context = FacesContext.getCurrentInstance();
    Map map = context.getExternalContext().getRequestParameterMap();
    String paramName = "title["+event.getFile().getFileName()+"]";
    String fileWithTitle = (String) map.get(paramName);            
}

Here's the full implementation of the add option (assuming your widgetVar is fileUpload)

$(document).ready(function() {
   setTimeout(fileUpload, 1000);
})

function fileUpload() {

PF('fileUpload').jq.fileupload({
    add: function(e, data) {
        $this = PF('fileUpload');
        $this.chooseButton.removeClass('ui-state-hover ui-state-focus');
        if ($this.files.length === 0) {
            $this.enableButton($this.uploadButton);
            $this.enableButton($this.cancelButton);
        }

        if ($this.cfg.fileLimit && ($this.uploadedFileCount + $this.files.length + 1) > $this.cfg.fileLimit) {
            $this.clearMessages();
            $this.showMessage({
                summary: $this.cfg.fileLimitMessage
            });

            return;
        }

        var file = data.files ? data.files[0] : null;
        if (file) {
            var validMsg = $this.validate(file);

            if (validMsg) {
                $this.showMessage({
                    summary: validMsg,
                    filename: file.name,
                    filesize: file.size
                });
            }
            else {
                $this.clearMessages();                                                                               
                //the only modification we have to do
                var row = $('<tr></tr>').append('<td class="ui-fileupload-preview"></td>')
                        .append('<td>' + file.name + '</td>')
                        .append('<td class="title"><label>Title: <input name="title['+ file.name +']"></label></td>') 
                        .append('<td>' + $this.formatSize(file.size) + '</td>')
                        .append('<td class="ui-fileupload-progress"></td>')
                        .append('<td><button class="ui-fileupload-cancel ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only"><span class="ui-button-icon-left ui-icon ui-icon ui-icon-close"></span><span class="ui-button-text">ui-button</span></button></td>')
                        .appendTo($this.filesTbody);

                
                if ($this.isCanvasSupported() && window.File && window.FileReader && $this.IMAGE_TYPES.test(file.name)) {
                    var imageCanvas = $('<canvas></canvas')
                            .appendTo(row.children('td.ui-fileupload-preview')),
                            context = imageCanvas.get(0).getContext('2d'),
                            winURL = window.URL || window.webkitURL,
                            url = winURL.createObjectURL(file),
                            img = new Image();

                    img.onload = function() {
                        var imgWidth = null, imgHeight = null, scale = 1;

                        if ($this.cfg.previewWidth > this.width) {
                            imgWidth = this.width;
                        }
                        else {
                            imgWidth = $this.cfg.previewWidth;
                            scale = $this.cfg.previewWidth / this.width;
                        }

                        var imgHeight = parseInt(this.height * scale);

                        imageCanvas.attr({width: imgWidth, height: imgHeight});
                        context.drawImage(img, 0, 0, imgWidth, imgHeight);
                    }

                    img.src = url;
                }

                //progress
                row.children('td.ui-fileupload-progress').append('<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="ui-progressbar-value ui-widget-header ui-corner-left" style="display: none; width: 0%;"></div></div>');

                file.row = row;

                file.row.data('filedata', data);
                $this.files.push(file);

                if ($this.cfg.auto) {
                    $this.upload();
                }
            }
        }
    }});
}

Just included the above code in some js file and included it before the end of </h:body>

Here's an online Demo.

Note: the only drag you might have in this approach, if the user has selected multiple files with the same exact name and extension you would get the first title twice!, for some this would be okay, since the user isn't supposed to upload identical files.

This is test on PrimeFaces 5.0 and Chrome.

这篇关于使用额外的 inputText 上传多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆