WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。
jsp代码
1 <div class="upload_buttoncontainer"> 2 <button class="upload_accredit" 3 onclick="showuploadimagesPage('upload','fade')">//onclik是打开一个窗口 4 <label>批量上传</label> 5 </button> 6 </div>
js代码
1 (function( $ ){ 2 // 当domReady的时候开始初始化 3 $(function() { 4 var $wrap = $('#uploader'), 5 6 // 图片容器 7 $queue = $( '<ul id="filelist" class="filelist"></ul>' ) 8 .appendTo( $wrap.find( '.queueList' ) ), 9 10 // 状态栏,包括进度和控制按钮 11 $statusBar = $wrap.find( '.statusBar' ), 12 13 // 文件总体选择信息。 14 $info = $statusBar.find( '.info' ), 15 16 // 上传按钮 17 $upload = $wrap.find( '.uploadBtn' ), 18 19 // 没选择文件之前的内容。 20 $placeHolder = $wrap.find( '.placeholder' ), 21 22 $progress = $statusBar.find( '.progress' ).hide(), 23 24 // 添加的文件数量 25 fileCount = 0, 26 27 // 添加的文件总大小 28 fileSize = 0, 29 30 // 优化retina, 在retina下这个值是2 31 ratio = window.devicePixelRatio || 1, 32 33 // 缩略图大小 34 thumbnailWidth = 110 * ratio, 35 thumbnailHeight = 110 * ratio, 36 37 // 可能有pedding, ready, uploading, confirm, done. 38 state = 'pedding', 39 40 // 所有文件的进度信息,key为file id 41 percentages = {}, 42 // 判断浏览器是否支持图片的base64 43 isSupportBase64 = ( function() { 44 var data = new Image(); 45 var support = true; 46 data.onload = data.onerror = function() { 47 if( this.width != 1 || this.height != 1 ) { 48 support = false; 49 } 50 } 51 data.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; 52 return support; 53 } )(), 54 55 // 检测是否已经安装flash,检测flash的版本 56 flashVersion = ( function() { 57 var version; 58 59 try { 60 version = navigator.plugins[ 'Shockwave Flash' ]; 61 version = version.description; 62 } catch ( ex ) { 63 try { 64 version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash') 65 .GetVariable('$version'); 66 } catch ( ex2 ) { 67 version = '0.0'; 68 } 69 } 70 version = version.match( /\d+/g ); 71 return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 ); 72 } )(), 73 74 supportTransition = (function(){ 75 var s = document.createElement('p').style, 76 r = 'transition' in s || 77 'WebkitTransition' in s || 78 'MozTransition' in s || 79 'msTransition' in s || 80 'OTransition' in s; 81 s = null; 82 return r; 83 })(), 84 85 // WebUploader实例 86 uploader; 87 88 if ( !WebUploader.Uploader.support('flash') && WebUploader.browser.ie ) { 89 90 // flash 安装了但是版本过低。 91 if (flashVersion) { 92 (function(container) { 93 window['expressinstallcallback'] = function( state ) { 94 switch(state) { 95 case 'Download.Cancelled': 96 alert('您取消了更新!') 97 break; 98 99 case 'Download.Failed': 100 alert('安装失败') 101 break; 102 103 default: 104 alert('安装已成功,请刷新!'); 105 break; 106 } 107 delete window['expressinstallcallback']; 108 }; 109 110 var swf = './expressInstall.swf'; 111 // insert flash object 112 var html = '<object type="application/' + 113 'x-shockwave-flash" data="' + swf + '" '; 114 115 if (WebUploader.browser.ie) { 116 html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '; 117 } 118 119 html += 'width="100%" height="100%" style="outline:0">' + 120 '<param name="movie" value="' + swf + '" />' + 121 '<param name="wmode" value="transparent" />' + 122 '<param name="allowscriptaccess" value="always" />' + 123 '</object>'; 124 125 container.html(html); 126 127 })($wrap); 128 129 // 压根就没有安转。 130 } else { 131 $wrap.html('<a href="http://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img alt="get flash player" src="http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg" /></a>'); 132 } 133 134 return; 135 } else if (!WebUploader.Uploader.support()) { 136 alert( 'Web Uploader 不支持您的浏览器!'); 137 return; 138 } 139 140 // 实例化 141 uploader = WebUploader.create({ 142 pick: { 143 id: '#filePicker', 144 label: '点击选择文件' 145 }, 146 formData: { 147 uid: 123 148 }, 149 compress: false,//不启用压缩 150 resize: false,//尺寸不改变 151 dnd: '#dndArea', 152 paste: '#uploader', 153 swf: '../js/Uploader.swf', 154 server: ‘后台’, 155 method:'POST', 156 157 158 159 // runtimeOrder: 'flash', 160 161 accept: { 162 title: 'Images', 163 extensions: 'gif,jpg,jpeg,bmp,png', 164 mimeTypes: 'image/*' 165 }, 166 167 // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。 168 disableGlobalDnd: true, 169 fileNumLimit: 300, 170 fileSizeLimit: 2000 * 1024 * 1024, // 200 M 171 fileSingleSizeLimit: 500 * 1024 * 1024 // 50 M 172 }); 173 174 // 拖拽时不接受 js, txt 文件。 175 uploader.on( 'dndAccept', function( items ) { 176 var denied = false, 177 len = items.length, 178 i = 0, 179 // 修改js类型 180 unAllowed = 'text/plain;application/javascript '; 181 182 for ( ; i < len; i++ ) { 183 // 如果在列表里面 184 if ( ~unAllowed.indexOf( items[ i ].type ) ) { 185 denied = true; 186 break; 187 } 188 } 189 190 return !denied; 191 }); 192 193 // uploader.on('filesQueued', function() { 194 // uploader.sort(function( a, b ) { 195 // if ( a.name < b.name ) 196 // return -1; 197 // if ( a.name > b.name ) 198 // return 1; 199 // return 0; 200 // }); 201 // }); 202 203 // 添加“添加文件”的按钮, 204 uploader.addButton({ 205 id: '#filePicker2', 206 label: '继续添加' 207 }); 208 // 添加“添加下一个”模型的按钮, 209 /*uploader.addButton({ 210 id: '#addModel', 211 label: '添加下一个' 212 });*/ 213 uploader.on('ready', function() { 214 window.uploader = uploader; 215 }); 216 217 // 当有文件添加进来时执行,负责view的创建 218 function addFile( file ) { 219 var $li = $( '<li id="' + file.id + '"><div class="item">' + 220 '<p class="title">' + file.name + '</p>' + 221 '<p class="imgWrap"></p>'+ 222 '<p class="progress"><span></span></p>' + 223 '</div></li>' ), 224 225 $btns = $('<div class="file-panel">' + 226 '<span class="cancel">删除</span>' + 227 '<span class="rotateRight">向右旋转</span>' + 228 '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li.find('.item') ), 229 $prgress = $li.find('p.progress span'), 230 $wrap = $li.find( 'p.imgWrap' ), 231 $info = $('<p class="error"></p>'), 232 233 showError = function( code ) { 234 switch( code ) { 235 case 'exceed_size': 236 text = '文件大小超出'; 237 break; 238 239 case 'interrupt': 240 text = '上传暂停'; 241 break; 242 243 default: 244 text = '上传失败,请重试'; 245 break; 246 } 247 248 $info.text( text ).appendTo( $li ); 249 }; 250 251 if ( file.getStatus() === 'invalid' ) { 252 showError( file.statusText ); 253 } else { 254 // @todo lazyload 255 $wrap.text( '预览中' ); 256 uploader.makeThumb( file, function( error, src ) { 257 var img; 258 259 if ( error ) { 260 $wrap.text( '不能预览' ); 261 return; 262 } 263 264 if( isSupportBase64 ) { 265 img = $('<img src="'+src+'">'); 266 $wrap.empty().append( img ); 267 } 268 }, thumbnailWidth, thumbnailHeight ); 269 270 percentages[ file.id ] = [ file.size, 0 ]; 271 file.rotation = 0; 272 } 273 274 file.on('statuschange', function( cur, prev ) { 275 if ( prev === 'progress' ) { 276 $prgress.hide().width(0); 277 } else if ( prev === 'queued' ) { 278 $li.off( 'mouseenter mouseleave' ); 279 $btns.remove(); 280 } 281 282 // 成功 283 if ( cur === 'error' || cur === 'invalid' ) { 284 console.log( file.statusText ); 285 showError( file.statusText ); 286 percentages[ file.id ][ 1 ] = 1; 287 } else if ( cur === 'interrupt' ) { 288 showError( 'interrupt' ); 289 } else if ( cur === 'queued' ) { 290 percentages[ file.id ][ 1 ] = 0; 291 } else if ( cur === 'progress' ) { 292 $info.remove(); 293 $prgress.css('display', 'block'); 294 } else if ( cur === 'complete' ) { 295 $li.append( '<span class="success"></span>' ); 296 } 297 298 $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur ); 299 }); 300 301 $li.on( 'mouseenter', function() { 302 $btns.stop().animate({height: 30}); 303 }); 304 305 $li.on( 'mouseleave', function() { 306 $btns.stop().animate({height: 0}); 307 }); 308 309 $btns.on( 'click', 'span', function() { 310 var index = $(this).index(), 311 deg; 312 313 switch ( index ) { 314 case 0: 315 uploader.removeFile( file ); 316 return; 317 318 case 1: 319 file.rotation += 90; 320 break; 321 322 case 2: 323 file.rotation -= 90; 324 break; 325 } 326 327 if ( supportTransition ) { 328 deg = 'rotate(' + file.rotation + 'deg)'; 329 $wrap.css({ 330 '-webkit-transform': deg, 331 '-mos-transform': deg, 332 '-o-transform': deg, 333 'transform': deg 334 }); 335 } else { 336 $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')'); 337 // use jquery animate to rotation 338 // $({ 339 // rotation: rotation 340 // }).animate({ 341 // rotation: file.rotation 342 // }, { 343 // easing: 'linear', 344 // step: function( now ) { 345 // now = now * Math.PI / 180; 346 347 // var cos = Math.cos( now ), 348 // sin = Math.sin( now ); 349 350 // $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')"); 351 // } 352 // }); 353 } 354 355 356 }); 357 358 $li.appendTo( $queue ); 359 $('.filelist').sortable(); 360 } 361 362 // 负责view的销毁 363 function removeFile( file ) { 364 var $li = $('#'+file.id); 365 366 delete percentages[ file.id ]; 367 updateTotalProgress(); 368 $li.off().find('.file-panel').off().end().remove(); 369 } 370 371 function updateTotalProgress() { 372 var loaded = 0, 373 total = 0, 374 spans = $progress.children(), 375 percent; 376 377 $.each( percentages, function( k, v ) { 378 total += v[ 0 ]; 379 loaded += v[ 0 ] * v[ 1 ]; 380 } ); 381 382 percent = total ? loaded / total : 0; 383 384 385 spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' ); 386 spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' ); 387 updateStatus(); 388 } 389 390 function updateStatus() { 391 var text = '', stats; 392 393 if ( state === 'ready' ) { 394 text = '选中' + fileCount + '张图片,共' + 395 WebUploader.formatSize( fileSize ) + '。'; 396 } else if ( state === 'confirm' ) { 397 stats = uploader.getStats(); 398 if ( stats.uploadFailNum ) { 399 text = '已成功上传' + stats.successNum+ '文件,'+ 400 stats.uploadFailNum + '文件上传失败,<a class="retry" href="#">重新上传</a>失败或<a class="ignore" href="#">忽略</a>' 401 } 402 403 } else { 404 stats = uploader.getStats(); 405 text = '共' + fileCount + '个(' + 406 WebUploader.formatSize( fileSize ) + 407 '),已上传' + (stats.successNum+1) + '个'; 408 409 if ( stats.uploadFailNum ) { 410 text += ',失败' + stats.uploadFailNum + '个'; 411 } 412 } 413 414 $info.html( text ); 415 } 416 417 function setState( val ) { 418 var file, stats; 419 420 if ( val === state ) { 421 return; 422 } 423 424 $upload.removeClass( 'state-' + state ); 425 $upload.addClass( 'state-' + val ); 426 state = val; 427 428 switch ( state ) { 429 case 'pedding': 430 $placeHolder.removeClass( 'element-invisible' ); 431 $queue.hide(); 432 $statusBar.addClass( 'element-invisible' ); 433 uploader.refresh(); 434 break; 435 436 case 'ready': 437 $placeHolder.addClass( 'element-invisible' ); 438 $( '#filePicker2' ).removeClass( 'element-invisible'); 439 $queue.show(); 440 $statusBar.removeClass('element-invisible'); 441 uploader.refresh(); 442 break; 443 444 case 'uploading': 445 $( '#filePicker2' ).addClass( 'element-invisible' ); 446 $progress.show(); 447 $upload.text( '暂停上传' ); 448 break; 449 450 case 'paused': 451 $progress.show(); 452 $upload.text( '继续上传' ); 453 break; 454 455 case 'confirm': 456 $progress.hide(); 457 $( '#filePicker2' ).removeClass( 'element-invisible' ); 458 $upload.text( '开始上传' ); 459 /*$('#filePicker2 + .uploadBtn').click(function () { 460 window.location.reload(); 461 });*/ 462 stats = uploader.getStats(); 463 if ( stats.successNum && !stats.uploadFailNum ) { 464 setState( 'finish' ); 465 return; 466 } 467 break; 468 case 'finish': 469 stats = uploader.getStats(); 470 if ( stats.successNum ) { 471 document.getElementById("shareUrl").style.visibility = 'visible'; 472 createQrcode(); 473 } else { 474 // 没有成功的图片,重设 475 state = 'done'; 476 location.reload(); 477 } 478 break; 479 } 480 481 updateStatus(); 482 } 483 484 uploader.onUploadProgress = function( file, percentage ) { 485 var $li = $('#'+file.id), 486 $percent = $li.find('.progress span'); 487 488 $percent.css( 'width', percentage * 100 + '%' ); 489 percentages[ file.id ][ 1 ] = percentage; 490 updateTotalProgress(); 491 }; 492 493 uploader.onFileQueued = function( file ) { 494 fileCount++; 495 fileSize += file.size; 496 497 if ( fileCount === 1 ) { 498 $placeHolder.addClass( 'element-invisible' ); 499 $statusBar.show(); 500 } 501 502 addFile( file ); 503 setState( 'ready' ); 504 updateTotalProgress(); 505 }; 506 507 uploader.onFileDequeued = function( file ) { 508 fileCount--; 509 fileSize -= file.size; 510 511 if ( !fileCount ) { 512 setState( 'pedding' ); 513 } 514 515 removeFile( file ); 516 updateTotalProgress(); 517 518 }; 519 520 uploader.on( 'all', function( type ) { 521 var stats; 522 switch( type ) { 523 case 'uploadFinished': 524 setState( 'confirm' ); 525 break; 526 527 case 'startUpload': 528 setState( 'uploading' ); 529 break; 530 531 case 'stopUpload': 532 setState( 'paused' ); 533 break; 534 535 } 536 }); 537 538 uploader.onError = function( code ) { 539 alert( '图片重复' ); 540 }; 541 542 $upload.on('click', function() { 543 if ( $(this).hasClass( 'disabled' ) ) { 544 return false; 545 } 546 547 if ( state === 'ready' ) { 548 uploader.upload(); 549 } else if ( state === 'paused' ) { 550 uploader.upload(); 551 } else if ( state === 'uploading' ) { 552 uploader.stop(); 553 } 554 }); 555 556 $info.on( 'click', '.retry', function() { 557 uploader.retry(); 558 } ); 559 560 $info.on( 'click', '.ignore', function() { 561 alert( 'todo' ); 562 } ); 563 564 $upload.addClass( 'state-' + state ); 565 updateTotalProgress(); 566 }); 567 568 })( jQuery );
后台代码
MultipartFile 需要在配置文件中进行配置上传的文件的大小,在这里我就不贴出来了
1 public void uploadInformation(HttpServletRequest request, 2 HttpServletResponse response) { 3 System.out.println("收到图片!"); 4 MultipartHttpServletRequest Murequest = (MultipartHttpServletRequest) request; 5 Map<String, MultipartFile> files = Murequest.getFileMap();// 得到文件map对象 6 String upaloadUrl = new File(this.getClass().getClassLoader().getResource("/").getPath()).getParentFile().getParentFile() 7 .getAbsolutePath() 8 + "/upload/";// 得到当前工程路径拼接上文件名 9 File dir = new File(upaloadUrl); 10 if (!dir.exists())// 目录不存在则创建 11 dir.mkdirs(); 12 int counter = 0; 13 for (MultipartFile file : files.values()) { 14 counter++; 15 String fileName = file.getOriginalFilename(); 16 File tagetFile = new File(upaloadUrl + fileName);// 创建文件对象 17 if (!tagetFile.exists()) {// 文件名不存在 则新建文件,并将文件复制到新建文件中 18 try { 19 tagetFile.createNewFile(); 20 } catch (IOException e) { 21 e.printStackTrace(); 22 } 23 try { 24 file.transferTo(tagetFile); 25 } catch (IllegalStateException e) { 26 e.printStackTrace(); 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31 32 } 33 System.out.println("接收完毕"); 34 }
这样图片批量上传的功能就实现了,当然也可以批量上传文件,只不过需要一些变动,有兴趣的可以去http://fex.baidu.com/webuploader/ 研究一下。接下来就是选择多张图片进行压缩并保存到指定路径下,关于图片在页面的显示 在这里就略过了。接下来是关于压缩文件的action代码
1 public void yasuoIamges(HttpServletRequest request, 2 HttpServletResponse response) throws Exception { 3 String selids = request.getParameter("selTids");//选中图片的ID组成的字符串 4 String date_format = "yyyy-MM-dd_HH_mm_ss"; 5 SimpleDateFormat f = new 6 SimpleDateFormat(date_format); 7 List<File> filelist = new ArrayList<>(); 8 String[] uid = selids.split(","); 9 for (int i = 0; i < uid.length; i++) { 10 Images du = imagesService.getoneimage(Long 11 .valueOf(uid[i])); 12 filelist.add(new File(new File(this.getClass().getClassLoader() 13 .getResource("/").getPath()).getParentFile() 14 .getParentFile().getAbsolutePath() 15 + "/" + du.getDupath())); 16 } 17 String icpath = new File(this.getClass().getClassLoader() 18 .getResource("/").getPath()).getParentFile().getParentFile() 19 .getAbsolutePath() 20 + "/compress/"; 21 File dir = new File(icpath); 22 if (!dir.exists())// 目录不存在则创建 23 dir.mkdirs(); 24 String filename = (f.format(new Date())) + ".rar";// 压缩包格式可以改 25 FileOutputStream fos = new FileOutputStream(icpath + filename); 26 ZipOutputStream zos = null; 27 try { 28 zos = new ZipOutputStream(fos); 29 for (File srcFile : filelist) { 30 byte[] buf = new byte[BUFFER_SIZE]; 31 zos.putNextEntry(new ZipEntry(srcFile.getName())); 32 int len; 33 FileInputStream in = new FileInputStream(srcFile); 34 while ((len = in.read(buf)) != -1) { 35 zos.write(buf, 0, len); 36 } 37 zos.closeEntry(); 38 in.close(); 39 } 40 } catch (Exception e) { 41 throw new RuntimeException("zip error from ZipUtils", e); 42 } finally { 43 if (zos != null) { 44 try { 45 zos.close(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 } 50 } 51 52 }
第一次写博客很多东西不是很会说,请谅解,也希望大家能有所收获。