public class ProgressMonitorFileItemFactory extends DiskFileItemFactory { private File temporaryDirectory; private HttpServletRequest requestRef; private long requestLength; public ProgressMonitorFileItemFactory(HttpServletRequest request) {super();temporaryDirectory = (File)request.getSession().getServletContext().getAttribute("javax.servlet.context.tempdir");requestRef = request;String contentLength = request.getHeader("content-length");if(contentLength != null){requestLength= Long.parseLong(contentLength.trim());} } public FileItem createItem(String fieldName, String contentType,boolean isFormField, String fileName) {SessionUpdatingProgressObserver observer = null;if(isFormField == false) //这必须是一文件上传. observer = new SessionUpdatingProgressObserver(fieldName,fileName); ProgressMonitorFileItem item = new ProgressMonitorFileItem( fieldName,contentType,isFormField, fileName,2048,temporaryDirectory, observer,requestLength);return item; } ... public class SessionUpdatingProgressObserver implements ProgressObserver {private String fieldName;private String fileName;...public void setProgress(double progress) { if(request != null){request.getSession().setAttribute("FileUpload.Progress."+fieldName,progress);request.getSession().setAttribute("FileUpload.FileName."+fieldName,fileName); }} }} |
ProgressMonitorFileItemFactory Content-Length头由浏览器设置并且假定它是被设置的上传文件的精确长度。这种确定文件长度的方法确实限制了你在每次请求中上传的文件-如果有多个文件在该请求中被编码的话,不过这个值是不精确的。这是由于,浏览器仅仅发送一个Content-Length头,而不考虑上传的文件数目。
除了创建ProgressMonitorFileItem实例之外,ProgressMonitorFileItemFactory还注册了一个ProgressObserver实例,它将由ProgressMonitorFileItem来发送文件上传过程中的更新。我们所使用的ProgressObserver的实现(SessionUpdatingProgressObserver)针对被提交字段的id把进度百分数设置到用户的会话中。然后,这个值可以由JSF组件存取以便把更新发送给用户。
(四) ProgressMonitorFileItem类
public class ProgressMonitorFileItem extends DiskFileItem { private ProgressObserver observer; private long passedInFileSize; ... private boolean isFormField; ... @Override public OutputStream getOutputStream() throws IOException {OutputStream baseOutputStream = super.getOutputStream();if(isFormField == false){ return new BytesCountingOutputStream(baseOutputStream);}else{return baseOutputStream;} } ... private class BytesCountingOutputStream extends OutputStream{private long previousProgressUpdate;private OutputStream base;public BytesCountingOutputStream(OutputStream ous){ base = ous; } ...private void fireProgressEvent(int b){ bytesRead += b; ... double progress = (((double)(bytesRead)) / passedInFileSize); progress *= 100.0 observer.setProgress(); } }} |
ProgressMonitorFileItem把DiskFileItem的缺省OutputStream包装到一个BytesCountingOutputStream中,这可以在每次读取一定数目的字节后更新相关的ProgressObserver。
(五) 支持AJAX的JavaServer Faces(JSF)上传组件
这个组件负责生成HTML文件上传标签,显示一个进度条以监视文件上传,并且生成一旦文件上传成功需要被显示的组件。使用JavaServer Faces实现这个组件的一个主要优点是,大多数复杂性被隐藏起来。开发人员只需要把组件标签添加到JSP,而后由组件负责所有的AJAX及相关的进度条监控细节问题。下面的JSP代码片断用于把上传组件添加到页面上。
<comp:fileUpload value="#{uploadPageBean.uploadedFile}" uploadIcon="images/upload.png" styleClass="progressBarDiv" progressBarStyleClass="progressBar" cellStyleClass="progressBarCell" activeStyleClass="progressBarActiveCell"><%--下面是一旦文件上传完成将成为可见的组件--%><h:panelGrid columns="2" cellpadding="2" cellspacing="0" width="100%"><f:facet name="header"><h:outputText styleClass="text"value="文件上传成功." /></f:facet><h:panelGroup ><h:commandButton action="#{uploadPageBean.reset}"image="images/reset.png"/></h:panelGroup><h:panelGroup ><h:commandButton action="#{uploadPageBean.nextPage}"image="images/continue.png"/></h:panelGroup></h:panelGrid></comp:fileUpload>
文件上传组件的value属性需要用一个拥有一个FileItem的属性绑定到一个bean上。组件只有在该文件被服务器成功收到时才显示。 |
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:http://blog.itpub.net/7839366/viewspace-920184/