简体   繁体   English

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

[英]Is there a way to upload large files reliable using JSF2.2

I have a problem to upload large files to my server application (Tomcat7, JSF2.2, PrimeFaces). 我在将大文件上传到服务器应用程序(Tomcat7,JSF2.2,PrimeFaces)时遇到问题。 I would like to upload files up to 5 GB. 我想上传最大5 GB的文件。 This needs much time and the probability of a short connection lost is very high. 这需要很多时间,并且短连接丢失的可能性非常高。

Currently I tried the primefaces fileupload. 目前,我尝试了primefaces文件上传。 This works but if I lost the network connection then the upload stopped directly without any feedback on client or server side. 这可行,但是如果我失去了网络连接,则上传会直接停止,而不会在客户端或服务器端产生任何反馈。

Is there a way to make it reliable? 有没有办法使它可靠?

Also the possibility to resume a file upload would be very fine. 恢复文件上传的可能性也非常好。

I will try to answer my question... 我会尽力回答我的问题...

The best way to make an upload reliable and resumable into a JSF/Primefaces web application is the integration of the Javascript library resumable.js (or similar libaries based on it). 使上传文件可靠且可恢复到JSF / Primefaces Web应用程序中的最佳方法是集成Javascript库resumable.js (或基于该库的类似库)。

It uses the HTML5 File API which is supported by many modern browsers. 它使用许多现代浏览器都支持的HTML5 File API。

Integration/Implementation: 集成/实施:

On client-side you have to integrate the resumable.js library and some Javascript code to handle the upload. 在客户端,您必须集成resumable.js库和一些Javascript代码来处理上载。 For that the resumable.js library provide some events like uploadStart, fileSuccess and many more. 为此, resumable.js库提供了一些事件,例如uploadStart,fileSuccess等。 In combination with the PrimeFaces <p:remoteCommand> you can communicate from Javascript to the server-side web application. 与PrimeFaces <p:remoteCommand>结合使用,您可以从Javascript与服务器端Web应用程序进行通信。

Code Example: Add resumable.js JavaScript library 代码示例:添加resumable.js JavaScript库

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

Code Example: Initialize resumable object 代码示例:初始化可恢复对象

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);
        ...
    }
    ...
}

Code Example: Communication from Javascript to the Managed Bean 代码示例:从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>

The server-side needs a WebFilter to receive the GET and POST requests from resumable.js. 服务器端需要一个WebFilter来接收来自resumable.js的GET和POST请求。 You have to implement the doFilter method from javax.servlet.Filter interface. 您必须从javax.servlet.Filter接口实现doFilter方法。 This filter class uses another class (eg UploadFileManager) with static methods to check if a chunk already received and to save nonexistent chunks. 该过滤器类使用具有静态方法的另一个类(例如UploadFileManager)来检查是否已接收到块并保存不存在的块。 If the upload is complete, then the client can call their managed bean via a RemoteCommand. 如果上传完成,则客户端可以通过RemoteCommand调用其托管Bean。 The Bean itself can access the uploaded file by the same UploadFileManager class via a static method. Bean本身可以通过静态方法通过同一UploadFileManager类访问上载的文件。

Note: The UploadFileManager class with the static methods must be threadsafe! 注意:具有静态方法的UploadFileManager类必须是线程安全的!

Component diagram 组件图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM