欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WebUploader+SpringMVC实现文件上传功能

程序员文章站 2023-12-13 10:34:16
webuploader是由baidu团队开发的一个简单的以html5为主,flash为辅的现代文件上传组件。在现代的浏览器里面能充分发挥html5的优势,同时又不摒弃主流i...

webuploader是由baidu团队开发的一个简单的以html5为主,flash为辅的现代文件上传组件。在现代的浏览器里面能充分发挥html5的优势,同时又不摒弃主流ie浏览器,沿用原来的flash运行时,兼容ie6+,ios 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。 采用大文件分片并发上传,极大的提高了文件上传效率。

官方文档及更多示例请参考:

不扯废话了,由于我需要的只是上传图片功能,官网上边还说“webuploader只包含文件上传的底层实现,不包括ui部分,所以交互方面可以*发挥。”但是我又看到官网的例子不错,就把demo的js和css扒了下来.

WebUploader+SpringMVC实现文件上传功能

WebUploader+SpringMVC实现文件上传功能

前台相关代码:

jsp:

<%@ page language="java" contenttype="text/html; charset=utf-8"
 pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<!--引入css-->
<link rel="stylesheet" type="text/css" href="${basepath}/js/plugins/webuploader/webuploader.css" rel="external nofollow" >
<link rel="stylesheet" type="text/css" href="${basepath}/views/uploaderdemo/uploader_demo.css" rel="external nofollow" >
<!--引入js-->
<script src="${basepath}/js/jquery.min.js"></script>
<script src="${basepath}/js/plugins/webuploader/webuploader.js"></script>
<script src="${basepath}/js/bootstrap.min.js"></script>
<script src="${basepath}/views/uploaderdemo/uploader_demo.js"></script>
<title>uploadtest</title>
</head>
<body>
 <div id="post-container" class="container">
  <div class="page-container">
   <h1 id="demo">demo</h1>
   <p>您可以尝试文件拖拽,使用qq截屏工具,然后激活窗口后粘贴,或者点击添加图片按钮,来体验此demo.</p>
   <div id="uploader" class="wu-example">
    <div class="queuelist">
     <div id="dndarea" class="placeholder">
      <div id="filepicker"></div>
      <p>或将照片拖到这里,单次最多可选300张</p>
     </div>
    </div>
    <div class="statusbar" style="display: none;">
     <div class="progress">
      <span class="text">0%</span> <span class="percentage"></span>
     </div>
     <div class="info"></div>
     <div class="btns">
      <div id="filepicker2"></div>
      <div class="uploadbtn">开始上传</div>
     </div>
    </div>
   </div>
  </div>
 </div>
</body>
</html>

uploader_demo.js

jquery(function() {
 var $ = jquery, // just in case. make sure it's not an other libaray.
  $wrap = $('#uploader'),  // 图片容器
  $queue = $('<ul class="filelist"></ul>')
   .appendto( $wrap.find('.queuelist') ),  // 状态栏,包括进度和控制按钮
  $statusba $wrap.find('.statusbar'),
  // 文件总体选择信息。
  $info = $statusbar.find('.info'),
  // 上传按钮
  $upload = $wrap.find('.uploadbtn'),
  // 没选择文件之前的内容。
  $placeholder = $wrap.find('.placeholder'),
  // 总体进度条
  $progress = $statusbar.find('.progress').hide(),
  // 添加的文件数量
  filecount = 0,
  // 添加的文件总大小
  filesize = 0,
  // 优化retina, 在retina下这个值是2
  ratio = window.devicepixelratio || 1,
  // 缩略图大小
  thumbnailwidth = 110 * ratio,
  thumbnailheight = 110 * ratio,
  // 可能有pedding, ready, uploading, confirm, done.
  state = 'pedding',
  // 所有文件的进度信息,key为file id
  percentages = {},
  supporttransition = (function(){
   var s = document.createelement('p').style,
    r = 'transition' in s ||
      'webkittransition' in s ||
      'moztransition' in s ||
      'mstransition' in s ||
      'otransition' in s;
   s = null;
   return r;
  })(),
  // webuploader实例
  uploader;
 if ( !webuploader.uploader.support() ) {
  alert( 'web uploader 不支持您的浏览器!如果你使用的是ie浏览器,请尝试升级 flash 播放器');
  throw new error( 'webuploader does not support the browser you are using.' );
 }
 // 实例化
 uploader = webuploader.create({
  pick: {
   id: '#filepicker',
   label: '点击选择图片'
  },
  dnd: '#uploader .queuelist',
  paste: document.body,
  accept: {
   title: 'images',
   extensions: 'gif,jpg,jpeg,bmp,png',
   mimetypes: 'image/*'
  },
  // swf文件路径,就是控件下的swf文件地址
  swf: 'js/plugins/webuploader/uploader.swf',
  disableglobaldnd: true,
  chunked: true,
  // 文件接收服务端,写你要执行的方法就行
  **server: 'http://localhost:8080/test/upload.do?method=upload'**,
  filenumlimit: 300,
  filesizelimit: 5 * 1024 * 1024, // 200 m
  filesinglesizelimit: 1 * 1024 * 1024 // 50 m
 });
 // 添加“添加文件”的按钮,
 uploader.addbutton({
  id: '#filepicker2',
  label: '继续添加'
 });
 // 当有文件添加进来时执行,负责view的创建
 function addfile( file ) {
  var $li = $( '<li id="' + file.id + '">' +
    '<p class="title">' + file.name + '</p>' +
    '<p class="imgwrap"></p>'+
    '<p class="progress"><span></span></p>' +
    '</li>' ),
   $btns = $('<div class="file-panel">' +
    '<span class="cancel">删除</span>' +
    '<span class="rotateright">向右旋转</span>' +
    '<span class="rotateleft">向左旋转</span></div>').appendto( $li ),
   $prgress = $li.find('p.progress span'),
   $wrap = $li.find( 'p.imgwrap' ),
   $info = $('<p class="error"></p>'),
   showerror = function( code ) {
    switch( code ) {
     case 'exceed_size':
      text = '文件大小超出';
      break;
     case 'interrupt':
      text = '上传暂停';
      break;
     default:
      text = '上传失败,请重试';
      break;
    }
    $info.text( text ).appendto( $li );
   };
  if ( file.getstatus() === 'invalid' ) {
   showerror( file.statustext );
  } else {
   // @todo lazyload
   $wrap.text( '预览中' );
   uploader.makethumb( file, function( error, src ) {
    if ( error ) {
     $wrap.text( '不能预览' );
     return;
    }
    var img = $('<img src="'+src+'">');
    $wrap.empty().append( img );
   }, thumbnailwidth, thumbnailheight );
   percentages[ file.id ] = [ file.size, 0 ];
   file.rotation = 0;
  }
  file.on('statuschange', function( cur, prev ) {
   if ( prev === 'progress' ) {
    $prgress.hide().width(0);
   } else if ( prev === 'queued' ) {
    $li.off( 'mouseenter mouseleave' );
    $btns.remove();
   }
   // 成功
   if ( cur === 'error' || cur === 'invalid' ) {
    console.log( file.statustext );
    showerror( file.statustext );
    percentages[ file.id ][ 1 ] = 1;
   } else if ( cur === 'interrupt' ) {
    showerror( 'interrupt' );
   } else if ( cur === 'queued' ) {
    percentages[ file.id ][ 1 ] = 0;
   } else if ( cur === 'progress' ) {
    $info.remove();
    $prgress.css('display', 'block');
   } else if ( cur === 'complete' ) {
    $li.append( '<span class="success"></span>' );
   }
   $li.removeclass( 'state-' + prev ).addclass( 'state-' + cur );
  });
  $li.on( 'mouseenter', function() {
   $btns.stop().animate({height: 30});
  });
  $li.on( 'mouseleave', function() {
   $btns.stop().animate({height: 0});
  });
  $btns.on( 'click', 'span', function() {
   var index = $(this).index(),
    deg;
   switch ( index ) {
    case 0:
     uploader.removefile( file );
     return;
    case 1:
     file.rotation += 90;
     break;
    case 2:
     file.rotation -= 90;
     break;
   }
   if ( supporttransition ) {
    deg = 'rotate(' + file.rotation + 'deg)';
    $wrap.css({
     '-webkit-transform': deg,
     '-mos-transform': deg,
     '-o-transform': deg,
     'transform': deg
    });
   } else {
    $wrap.css( 'filter', 'progid:dximagetransform.microsoft.basicimage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
    // use jquery animate to rotation
    // $({
    //  rotation: rotation
    // }).animate({
    //  rotation: file.rotation
    // }, {
    //  easing: 'linear',
    //  step: function( now ) {
    //   now = now * math.pi / 180;
    //   var cos = math.cos( now ),
    //    sin = math.sin( now );
    //   $wrap.css( 'filter', "progid:dximagetransform.microsoft.matrix(m11=" + cos + ",m12=" + (-sin) + ",m21=" + sin + ",m22=" + cos + ",sizingmethod='auto expand')");
    //  }
    // });
   }
  });
  $li.appendto( $queue );
 }
 // 负责view的销毁
 function removefile( file ) {
  var $li = $('#'+file.id);
  delete percentages[ file.id ];
  updatetotalprogress();
  $li.off().find('.file-panel').off().end().remove();
 }
 function updatetotalprogress() {
  var loaded = 0,
   total = 0,
   spans = $progress.children(),
   percent;
  $.each( percentages, function( k, v ) {
   total += v[ 0 ];
   loaded += v[ 0 ] * v[ 1 ];
  } );
  percent = total ? loaded / total : 0;
  spans.eq( 0 ).text( math.round( percent * 100 ) + '%' );
  spans.eq( 1 ).css( 'width', math.round( percent * 100 ) + '%' );
  updatestatus();
 }
 function updatestatus() {
  var text = '', stats;
  if ( state === 'ready' ) {
   text = '选中' + filecount + '张图片,共' +
     webuploader.formatsize( filesize ) + '。';
  } else if ( state === 'confirm' ) {
   stats = uploader.getstats();
   if ( stats.uploadfailnum ) {
    text = '已成功上传' + stats.successnum+ '张照片至xx相册,'+
     stats.uploadfailnum + '张照片上传失败,<a class="retry" href="#" rel="external nofollow" rel="external nofollow" >重新上传</a>失败图片或<a class="ignore" href="#" rel="external nofollow" rel="external nofollow" >忽略</a>'
   }
  } else {
   stats = uploader.getstats();
   text = '共' + filecount + '张(' +
     webuploader.formatsize( filesize ) +
     '),已上传' + stats.successnum + '张';
   if ( stats.uploadfailnum ) {
    text += ',失败' + stats.uploadfailnum + '张';
   }
  }
  $info.html( text );
 }
 function setstate( val ) {
  var file, stats;
  if ( val === state ) {
   return;
  }
  $upload.removeclass( 'state-' + state );
  $upload.addclass( 'state-' + val );
  state = val;
  switch ( state ) {
   case 'pedding':
    $placeholder.removeclass( 'element-invisible' );
    $queue.parent().removeclass('filled');
    $queue.hide();
    $statusbar.addclass( 'element-invisible' );
    uploader.refresh();
    break;
   case 'ready':
    $placeholder.addclass( 'element-invisible' );
    $( '#filepicker2' ).removeclass( 'element-invisible');
    $queue.parent().addclass('filled');
    $queue.show();
    $statusbar.removeclass('element-invisible');
    uploader.refresh();
    break;
   case 'uploading':
    $( '#filepicker2' ).addclass( 'element-invisible' );
    $progress.show();
    $upload.text( '暂停上传' );
    break;
   case 'paused':
    $progress.show();
    $upload.text( '继续上传' );
    break;
   case 'confirm':
    $progress.hide();
    $upload.text( '开始上传' ).addclass( 'disabled' );
    stats = uploader.getstats();
    if ( stats.successnum && !stats.uploadfailnum ) {
     setstate( 'finish' );
     return;
    }
    break;
   case 'finish':
    stats = uploader.getstats();
    if ( stats.successnum ) {
     alert( '上传成功' );
    } else {
     // 没有成功的图片,重设
     state = 'done';
     location.reload();
    }
    break;
  }
  updatestatus();
 }
 uploader.onuploadprogress = function( file, percentage ) {
  var $li = $('#'+file.id),
   $percent = $li.find('.progress span');
  $percent.css( 'width', percentage * 100 + '%' );
  percentages[ file.id ][ 1 ] = percentage;
  updatetotalprogress();
 };
 uploader.onfilequeued = function( file ) {
  filecount++;
  filesize += file.size;
  if ( filecount === 1 ) {
   $placeholder.addclass( 'element-invisible' );
   $statusbar.show();
  }
  addfile( file );
  setstate( 'ready' );
  updatetotalprogress();
 };
 uploader.onfiledequeued = function( file ) {
  filecount--;
  filesize -= file.size;
  if ( !filecount ) {
   setstate( 'pedding' );
  }
  removefile( file );
  updatetotalprogress();
 };
 uploader.on( 'all', function( type ) {
  var stats;
  switch( type ) {
   case 'uploadfinished':
    setstate( 'confirm' );
    break;
   case 'startupload':
    setstate( 'uploading' );
    break;
   case 'stopupload':
    setstate( 'paused' );
    break;
  }
 });
 uploader.onerror = function( code ) {
  alert( 'eroor: ' + code );
 };
 $upload.on('click', function() {
  if ( $(this).hasclass( 'disabled' ) ) {
   return false;
  }
  if ( state === 'ready' ) {
   uploader.upload();
  } else if ( state === 'paused' ) {
   uploader.upload();
  } else if ( state === 'uploading' ) {
   uploader.stop();
  }
 });
 $info.on( 'click', '.retry', function() {
  uploader.retry();
 } );
 $info.on( 'click', '.ignore', function() {
  alert( 'todo' );
 } );
 $upload.addclass( 'state-' + state );
 updatetotalprogres});

uploader_demo.css

#container {
 color: #838383;
 font-size: 12px;
}
#uploader .queuelist {
 margin: 20px;
 border: 3px dashed #e6e6e6;
}
#uploader .queuelist.filled {
 padding: 17px;
 margin: 0;
 border: 3px dashed transparent;
}
#uploader .queuelist.webuploader-dnd-over {
 border: 3px dashed #999999;
}
#uploader p {margin: 0;}
.element-invisible {
 position: absolute !important;
 clip: rect(1px 1px 1px 1px); /* ie6, ie7 */
 clip: rect(1px,1px,1px,1px);
}
#uploader .placeholder {
 min-height: 350px;
 padding-top: 178px;
 text-align: center;
 background: url(../images/image.png) center 93px no-repeat;
 color: #cccccc;
 font-size: 18px;
 position: relative;
}
#uploader .placeholder .webuploader-pick {
 font-size: 18px;
 background: #00b7ee;
 border-radius: 3px;
 line-height: 44px;
 padding: 0 30px;
 *width: 120px;
 color: #fff;
 display: inline-block;
 margin: 0 auto 20px auto;
 cursor: pointer;
 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}
#uploader .placeholder .webuploader-pick-hover {
 background: #00a2d4;
}
#uploader .placeholder .flashtip {
 color: #666666;
 font-size: 12px;
 position: absolute;
 width: 100%;
 text-align: center;
 bottom: 20px;
}
#uploader .placeholder .flashtip a {
 color: #0785d1;
 text-decoration: none;
}
#uploader .placeholder .flashtip a:hover {
 text-decoration: underline;
}
#uploader .filelist {
 list-style: none;
 margin: 0;
 padding: 0;
}
#uploader .filelist:after {
 content: '';
 display: block;
 width: 0;
 height: 0;
 overflow: hidden;
 clear: both;
}
#uploader .filelist li {
 width: 110px;
 height: 110px;
 background: url(../images/bg.png) no-repeat;
 text-align: center;
 margin: 0 8px 20px 0;
 position: relative;
 display: inline;
 float: left;
 overflow: hidden;
 font-size: 12px;
}
#uploader .filelist li p.log {
 position: relative;
 top: -45px;
}
#uploader .filelist li p.title {
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 overflow: hidden;
 white-space: nowrap;
 text-overflow : ellipsis;
 top: 5px;
 text-indent: 5px;
 text-align: left;
}
#uploader .filelist li p.progress {
 position: absolute;
 width: 100%;
 bottom: 0;
 left: 0;
 height: 8px;
 overflow: hidden;
 z-index: 50;
 margin: 0;
 border-radius: 0;
 background: none;
 -webkit-box-shadow: 0 0 0;
}
#uploader .filelist li p.progress span {
 display: none;
 overflow: hidden;
 width: 0;
 height: 100%;
 background: #1483d8 url(../images/progress.png) repeat-x;
 -webit-transition: width 200ms linear;
 -moz-transition: width 200ms linear;
 -o-transition: width 200ms linear;
 -ms-transition: width 200ms linear;
 transition: width 200ms linear;
 -webkit-animation: progressmove 2s linear infinite;
 -moz-animation: progressmove 2s linear infinite;
 -o-animation: progressmove 2s linear infinite;
 -ms-animation: progressmove 2s linear infinite;
 animation: progressmove 2s linear infinite;
 -webkit-transform: translatez(0);
}
@-webkit-keyframes progressmove {
 0% {
  background-position: 0 0;
 }
 100% {
  background-position: 17px 0;
 }
}
@-moz-keyframes progressmove {
 0% {
  background-position: 0 0;
 }
 100% {
  background-position: 17px 0;
 }
}
@keyframes progressmove {
 0% {
  background-position: 0 0;
 }
 100% {
  background-position: 17px 0;
 }
}
#uploader .filelist li p.imgwrap {
 position: relative;
 z-index: 2;
 line-height: 110px;
 vertical-align: middle;
 overflow: hidden;
 width: 110px;
 height: 110px;
 -webkit-transform-origin: 50% 50%;
 -moz-transform-origin: 50% 50%;
 -o-transform-origin: 50% 50%;
 -ms-transform-origin: 50% 50%;
 transform-origin: 50% 50%;
 -webit-transition: 200ms ease-out;
 -moz-transition: 200ms ease-out;
 -o-transition: 200ms ease-out;
 -ms-transition: 200ms ease-out;
 transition: 200ms ease-out;
}
#uploader .filelist li img {
 width: 100%;
}
#uploader .filelist li p.error {
 background: #f43838;
 color: #fff;
 position: absolute;
 bottom: 0;
 left: 0;
 height: 28px;
 line-height: 28px;
 width: 100%;
 z-index: 100;
}
#uploader .filelist li .success {
 display: block;
 position: absolute;
 left: 0;
 bottom: 0;
 height: 40px;
 width: 100%;
 z-index: 200;
 background: url(../images/success.png) no-repeat right bottom;
}
#uploader .filelist div.file-panel {
 position: absolute;
 height: 0;
 filter: progid:dximagetransform.microsoft.gradient(gradienttype=0,startcolorstr='#80000000', endcolorstr='#80000000')\0;
 background: rgba( 0, 0, 0, 0.5 );
 width: 100%;
 top: 0;
 left: 0;
 overflow: hidden;
 z-index: 300;
}
#uploader .filelist div.file-panel span {
 width: 24px;
 height: 24px;
 display: inline;
 float: right;
 text-indent: -9999px;
 overflow: hidden;
 background: url(../../img/uploader_icons.png) no-repeat;
 margin: 5px 1px 1px;
 cursor: pointer; 
}
#uploader .filelist div.file-panel span.rotateleft {
 background-position: 0 -24px;
}
#uploader .filelist div.file-panel span.rotateleft:hover {
 background-position: 0 0;
}
#uploader .filelist div.file-panel span.rotateright {
 background-position: -24px -24px;
}
#uploader .filelist div.file-panel span.rotateright:hover {
 background-position: -24px 0;
}
#uploader .filelist div.file-panel span.cancel {
 background-position: -48px -24px;
}
#uploader .filelist div.file-panel span.cancel:hover {
 background-position: -48px 0;
}
#uploader .statusbar {
 height: 63px;
 border-top: 1px solid #dadada;
 padding: 0 20px;
 line-height: 63px;
 vertical-align: middle;
 position: relative;
}
#uploader .statusbar .progress {
 border: 1px solid #1483d8;
 width: 198px;
 background: #fff;
 height: 18px;
 position: relative;
 display: inline-block;
 text-align: center;
 line-height: 20px;
 color: #6dbfff;
 position: relative;
 margin: 0 10px 0 0;
}
#uploader .statusbar .progress span.percentage {
 width: 0;
 height: 100%;
 left: 0;
 top: 0;
 background: #1483d8;
 position: absolute;
}
#uploader .statusbar .progress span.text {
 position: relative;
 z-index: 10;
}
#uploader .statusbar .info {
 display: inline-block;
 font-size: 14px;
 color: #666666;
}
#uploader .statusbar .btns {
 position: absolute;
 top: 10px;
 right: 20px;
 line-height: 40px;
}
#filepicker2 {
 display: inline-block;
 float: left;
}
#uploader .statusbar .btns .webuploader-pick,
#uploader .statusbar .btns .uploadbtn,
#uploader .statusbar .btns .uploadbtn.state-uploading,
#uploader .statusbar .btns .uploadbtn.state-paused {
 background: #ffffff;
 border: 1px solid #cfcfcf;
 color: #565656;
 padding: 0 18px;
 display: inline-block;
 border-radius: 3px;
 margin-left: 10px;
 cursor: pointer;
 font-size: 14px;
 float: left;
}
#uploader .statusbar .btns .webuploader-pick-hover,
#uploader .statusbar .btns .uploadbtn:hover,
#uploader .statusbar .btns .uploadbtn.state-uploading:hover,
#uploader .statusbar .btns .uploadbtn.state-paused:hover {
 background: #f0f0f0;
}
#uploader .statusbar .btns .uploadbtn {
 background: #00b7ee;
 color: #fff;
 border-color: transparent;
}
#uploader .statusbar .btns .uploadbtn:hover {
 background: #00a2d4;
}
#uploader .statusbar .btns .uploadbtn.disabled {
 pointer-events: none;
 opacity: 0.6;
}

后台代码:

@controller
@requestmapping("/upload")
public class uploadertestcontroller {
 @requestmapping(params = "method=uploadpic")
 public string uploadpic(httpservletrequest request){
  return "uploaderdemo/uploadertest";
 }
 @requestmapping(params="method=upload")
 @responsebody
 public string uploads(@requestparam("file")multipartfile sortpicimg,httpservletrequest request,httpservletresponse response) {
  string path = sysconstants.pic_server_file_root_dir +sysconstants.pic_ptype_dir ;
  string filename = system.currenttimemillis()+"_"+sortpicimg.getoriginalfilename();
  file targetfile = new file(path, filename);
  if (!targetfile.exists()) {
   targetfile.mkdirs();
  }
  jsonobject json = new jsonobject();
  //保存
  try {
   sortpicimg.transferto(targetfile);
  } catch (exception e) {
   e.printstacktrace();
   json.put("msg","error");
   return json.tojsonstring();
  }
  json.put("msg","success");
  //json.put("filepath",request.getcontextpath() + "/upload/" + filename);
  file retfile = new file(sysconstants.pic_server_dns +sysconstants.pic_ptype_dir, filename);
  json.put("filepath",retfile.getpath());
  system.out.println("json="+json.tojsonstring());
  return json.tojsonstring();
 }
 }

前台传到后台的图片是一张一张传的,每传一张图片调用一次该server方法,直到传完为止。

将图片文件上传到图片服务器后,再将该图片地址存储在数据库中。

上一篇:

下一篇: