struts2实现文件上传显示进度条效果
一.struts2读取进度原理分析(作为草稿存了好久,刚刚发布出来......)
1.在strut2中控制文件上传信息的类是实现MultiPartRequest接口的JakartaMultiPartRequest
其实第一次看到源文件时我打了个退堂鼓,因为觉得内容太长了,不想看。冷静下来将思路理顺,将分开的各个方法还原到一个方方中中,发现还是很好理解的:
@Override
publicvoidparse(HttpServletRequestrequest,StringsaveDir)
throwsIOException{
setLocale(request);
//规定了File文件的格式(如文件名必须是xxFileName,文件类型xxContentType),并定义了File的保存路径DiskFileItemFactoryfactory=newDiskFileItemFactory();
ServletFileUploadupload=newServletFileUpload(factory);//处理文件上传的servlet
upload.setProgressListener(newFileUploadProgressListener(request));//为文件上传添加监听factory.setSizeThreshold(0);//if(saveDir!=null
factory.setRepository(newFile(saveDir));//临时路径
}
try{
upload.setSizeMax(maxSize);
Listitems=upload.parseRequest(createRequestContext(request));//获取所有请求
for(ObjectobItem:items){
FileItemitem=(FileItem)obItem;//获取每个请求的文件
if(LOG.isDebugEnabled()){
LOG.debug("Founditem"+item.getFieldName());
}
if(item.isFormField()){//普通表单提交
LOG.debug("Itemisanormalformfield");
Listvalues;
if(params.get(item.getFieldName())!=null){
values=params.get(item.getFieldName());
}else{
values=newArrayList();
}
Stringcharset=request.getCharacterEncoding();
if(charset!=null){
values.add(item.getString(charset));
}else{
values.add(item.getString());
}
params.put(item.getFieldName(),values);
}else{//文件上传请求
LOG.debug("Itemisafileupload");
if(item.getName()==null
||item.getName().trim().length()<=0){
LOG.debug("Nofilehasbeenuplodedforthefiled:"
+item.getFieldName());
continue;
}
Listvalues;
if(files.get(item.getFieldName())!=null){
values=files.get(item.getFieldName());
}else{
values=newArrayList();
}
values.add(item);
files.put(item.getFieldName(),values);
}
}
}catch(FileUploadBase.SizeLimitExceededExceptione){
System.out.println("错误1:"+e);
if(LOG.isWarnEnabled()){
LOG.warn("Requestexceededsizelimit!",e);
}
StringerrorMessage=buildErrorMessage(e,newObject[]{e.getPermittedSize(),e.getActualSize()});
if(!errors.contains(errorMessage)){
errors.add(errorMessage);
}
}catch(Exceptione){
System.out.println("错误1:"+e);
if(LOG.isWarnEnabled()){
LOG.warn("Unabletoparserequest",e);
}
StringerrorMessage=buildErrorMessage(e,newObject[]{});
if(!errors.contains(errorMessage)){
errors.add(errorMessage);
}
}
}
2. 文件上传监听文件FileUploadProgressListener.java
publicclassFileUploadProgressListenerimplementsProgressListener{
privatefinalHttpSessionsession;
privatefinalDecimalFormatformat=newDecimalFormat("#00.0");
publicFileUploadProgressListener(HttpServletRequestrequest){
session=request.getSession();
FileUploadStatusstatus=newFileUploadStatus();
session.setAttribute("uploadStatus",status);
}
@Override
publicvoidupdate(longpBytesRead,longpContentLength,intpItems){
FileUploadStatusuploadStatus=(FileUploadStatus)session.getAttribute("uploadStatus");
DoubleuploadRate=(double)(pBytesRead*100/pContentLength);
uploadStatus.setUploadRate(Double.valueOf(format.format(uploadRate)));
uploadStatus.setReadedBytes(pBytesRead/1024);
uploadStatus.setTotalBytes(pContentLength/1024);
uploadStatus.setCurrentItems(pItems);
}
}
3.添加状态文件:FileUploadStatus.java
publicclassFileUploadStatus{
privateDoubleuploadRate=0.0;
privateLongreadedBytes=0L;
privateLongtotalBytes=0L;
privateintcurrentItems=0;
privateLonguploadSpeed=0L;
privateLongstartTime=System.currentTimeMillis();
privateLongreadedTimes=0L;
privateLongtotalTimes=0L;
//"-1"错误"0"正常"1"完成
privateStringerror="0";
...
settergetter方法
...
}
4.Action类(如果是多文件上传,则将File FileName ContentType定义成数组形式即可)
/**
*利用io流上传文件
*/
publicclassFileStreamUploadActionextendsActionSupport{
/**
*serialVersionUID作用:---相当于类的身份证。序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
*有两种生成方式:一个是默认的1L,比如:privatestaticfinallongserialVersionUID=1L;
*一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:privatestaticfinallong
*serialVersionUID=xxxxL;
*/
privatestaticfinallongserialVersionUID=1L;
privateFileimage;
privateStringimageFileName;
privateStringimageContentType;
privateStringmessage;
publicStringuploadFile(){
FileInputStreamin=null;
FileOutputStreamout=null;
System.out.println("文件名:"+imageFileName);
try{
this.setNewFileName(imageFileName);
StringrealPath=ServletActionContext.getServletContext()
.getRealPath("/file");
FilefilePath=newFile(realPath);
if(!filePath.exists()){//如果保存的路径不存在则创建
filePath.mkdir();
}
if(image==null){
message="上传文件为空";
System.out.println(message);
}else{
FilesaveFile=newFile(filePath,this.getNewFileName());
out=newFileOutputStream(saveFile);
}
in=newFileInputStream(image);
byte[]byt=newbyte[1024];
intlength=0;
while((length=in.read(byt))>0){
out.write(byt,0,length);
out.flush();
}
message="上传成功";
System.out.println(message);
}catch(FileNotFoundExceptione){
message="找不到文件!";
e.printStackTrace();
}catch(IOExceptione){
message="文件读取失败!";
e.printStackTrace();
}finally{
closeStream(in,out);
}
return"uploadSucc";
}
publicvoidcloseStream(FileInputStreamin,FileOutputStreamout){
try{
if(in!=null){
in.close();
}
if(out!=null){
out.close();
}
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
...
setter()getter()
...
}
获取进度的Action
publicclassFileProgressActionextendsActionSupport{
privatestaticfinallongserialVersionUID=1L;
privateFileUploadStatusuploadStatus;
publicStringuploadPercent(){
HttpSessionsession=ServletActionContext.getRequest().getSession();
this.uploadStatus=(FileUploadStatus)session.getAttribute("uploadStatus");
if(uploadStatus==null){
System.out.println("actionisnull");
uploadStatus=newFileUploadStatus();
uploadStatus.setCurrentItems(0);
}
return"getPercent";
}
publicFileUploadStatusgetUploadStatus(){
returnuploadStatus;
}
publicvoidsetUploadStatus(FileUploadStatusuploadStatus){
this.uploadStatus=uploadStatus;
}
}
5.struts.xml中
newFileName text/html uploadStatus
二. 进度条显示
View页面设置,利用ajaxfileupload.js来获取文件并进行异步上传,bootstrap中的进度条效果显示进度(利用setInterval间断的获取进度信息来形式一种进度的前进显示)
Inserttitlehere /bootstrap/js/bootstrap.js"> /bootstrap/js/jquery.showLoading.min.js"> varsetinterval; $(document).ready(function(){ $("#upload").click(function(){ $("#upload").addClass("disabled"); $("#upload").attr("disabled",true); $("#upload").attr("title","文件上传中..."); uploadFile(); setinterval=setInterval(uploadProgress,200); }); }); //文件上传 functionuploadFile(){ $.ajaxFileUpload({ url:'ajaxUploadFile_uploadFile.action', secureuri:false,//是否采用安全协议,默认为false fileElementId:'image', dataType:'json', success:function(data){ $("#showImage").attr("src","/FileUpLoadTest/file/"+data); } }); } //上传进度 functionuploadProgress(){ $.get("uploadPercent_uploadPercent.action","",function(data){ $("#ProgressRate").html("上传速度:"+data.uploadRate+"%"); $("#readBytes").html("以读取:"+data.readedBytes+"KB"); $("#totalBytes").html("总大小:"+data.totalBytes+"KB"); $("#progress").attr("style","width:"+data.uploadRate+"%;"); $("#progress").html(data.uploadRate+"%"); if(data.uploadRate==100){ clearInterval(setinterval); $("#progress").html("上传成功"); $("#upload").removeClass("disabled"); $("#upload").attr("disabled",false); } }); } 文件异步上传+进度条