【发布时间】:2015-12-03 18:53:32
【问题描述】:
我无法将大文件上传到我的服务器应用程序(Tomcat7、JSF2.2、PrimeFaces)。我想上传最大 5 GB 的文件。这需要很多时间,而且短连接丢失的可能性非常高。
目前我尝试了 primefaces 文件上传。这可行,但如果我失去了网络连接,那么上传会直接停止,而客户端或服务器端没有任何反馈。
有没有办法让它可靠?
还可以恢复文件上传。
【问题讨论】:
标签: jsf file-upload primefaces
我无法将大文件上传到我的服务器应用程序(Tomcat7、JSF2.2、PrimeFaces)。我想上传最大 5 GB 的文件。这需要很多时间,而且短连接丢失的可能性非常高。
目前我尝试了 primefaces 文件上传。这可行,但如果我失去了网络连接,那么上传会直接停止,而客户端或服务器端没有任何反馈。
有没有办法让它可靠?
还可以恢复文件上传。
【问题讨论】:
标签: jsf file-upload primefaces
我会尽量回答我的问题...
使上传可靠且可恢复到 JSF/Primefaces Web 应用程序的最佳方法是集成 Javascript 库 resumable.js(或基于它的类似库)。
它使用许多现代浏览器都支持的 HTML5 File 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 请求。您必须从javax.servlet.Filter 接口实现doFilter 方法。
此过滤器类使用另一个具有静态方法的类(例如 UploadFileManager)来检查是否已收到块并保存不存在的块。
如果上传完成,那么客户端可以通过 RemoteCommand 调用他们的托管 bean。 Bean本身可以通过同一个UploadFileManager类通过静态方法访问上传的文件。
注意:带有静态方法的 UploadFileManager 类必须是线程安全的!
【讨论】: