有没有办法使用JSF2.2上传可靠的大文件

时间:2014-12-18 15:52:52

标签: jsf file-upload primefaces

我将大文件上传到我的服务器应用程序(Tomcat7,JSF2.2,PrimeFaces)时遇到问题。我想上传最大5 GB的文件。这需要很多时间,并且短连接丢失的可能性非常高。

目前我尝试了primefaces fileupload。这可以工作,但是如果我丢失了网络连接,那么上传就会直接停止,而无需客户端或服务器端的任何反馈。

有没有办法让它可靠?

此外,恢复文件上传的可能性非常好。

1 个答案:

答案 0 :(得分:0)

我会尽力回答我的问题......

将上传可靠并可恢复到JSF / Primefaces Web应用程序的最佳方法是集成Javascript库 resumable.js (或基于它的类似库)。

它使用许多现代浏览器支持的HTML5文件API。

集成/执行:

在客户端,您必须集成resumable.js库和一些Javascript代码来处理上传。为此,resumable.js库提供了一些事件,如uploadStart,fileSuccess等等。 结合PrimeFaces <p:remoteCommand>,您可以从Javascript与服务器端Web应用程序进行通信。

代码示例:添加resumable.js JavaScript库

<h:outputScript library="js" name="resumable.js" />

代码示例:初始化可恢复对象

var r;
var maxFileSize = #{uploadDataBean.getUploadSizeLimit()};
var allowedFileExtensions = #{uploadDataBean.getFileTypes()};

function pageLoaded() {
    PF('wVarStartBtn').disable();

    r = new Resumable({
        target: '../upload',
        chunkSize: 1*1024*1024,
        forceChunkSize: true,
        prioritizeFirstAndLastChunk: false,
        simultaneousUploads: 3,
        testChunks: true,
        chunkRetryInterval: 1000,
        maxFiles: 1,
        maxFilesErrorCallback: callbackMaxFiles,
        maxFileSize: maxFileSize,
        maxFileSizeErrorCallback: callbackMaxFileSize,
        fileType: allowedFileExtensions,
        fileTypeErrorCallback: callbackFileType,
        method: "octet"
    });

    r.assignDrop($('.resumable-drop')[0]);
    r.assignBrowse($('.resumable-select')[0]);

    // ### resumable event functions ###
    r.on('fileAdded', function(file) {
        console.log("File added: Name = " + file.fileName + ", No. of Chunks = " + file.chunks.length);
        ...
    }
    ...
}

代码示例:从Javascript到托管Bean的通信

<h:form id="hiddenInputsForm" prependId="false" style="display:none;">
    <p:remoteCommand name="rcStartUpload" update=":msg :msgs" actionListener="#{uploadDataBean.uploadStarted()}" />
    <p:remoteCommand name="rcUploadComplete" update=":msg :msgs" actionListener="#{uploadDataBean.uploadComplete()}" />
    <p:remoteCommand name="rcAddFile" update="hiddenInputsForm" />
    <h:inputText id="fileupload-hidden-input-filename" value="#{uploadDataBean.fileName}" />
    <h:inputText id="fileupload-hidden-input-fileidentifer" value="#{uploadDataBean.fileIdentifier}" />
    <h:inputText id="fileupload-hidden-input-filesize" value="#{uploadDataBean.fileSize}" />
    <h:inputText id="fileupload-hidden-input-chunksize" value="#{uploadDataBean.chunkSize}" />
</h:form>

<script type="text/javascript">
    ...

    function pageLoaded() {
        ...        
        // ### resumable event functions ###
        r.on('fileAdded', function(file) {
            console.log("File added: Name = " + file.fileName + ", No. of Chunks = " + file.chunks.length);

            document.getElementById('fileupload-hidden-input-filename').value = file.fileName;
            document.getElementById('fileupload-hidden-input-fileidentifer').value = file.uniqueIdentifier;
            document.getElementById('fileupload-hidden-input-filesize').value = file.size;
            document.getElementById('fileupload-hidden-input-chunksize').value = file.chunks.length;

            rcAddFile();

        });
        r.on('uploadStart', function () {
            console.log("Upload started");
            rcStartUpload();
        })
        r.on('fileSuccess', function(file) {
            console.log("File upload success");
            rcUploadComplete();
        });
        ...
    }

</script>

服务器端需要WebFilter来接收来自resumable.js的GET和POST请求。您必须从doFilter接口实现javax.servlet.Filter方法。 此过滤器类使用另一个类(例如UploadFileManager)和静态方法来检查是否已收到块并保存不存在的块。 如果上载完成,则客户端可以通过RemoteCommand调用其托管bean。 Bean本身可以通过静态方法通过相同的UploadFileManager类访问上载的文件。

注意:带有静态方法的UploadFileManager类必须是线程安全的!

Component diagram