弄了好久终于把 这两个组件给弄清楚了,webuploader 前端插件,smartUpload java上传文件组件。
前端代码:
<label class="form-label col-xs-4 col-sm-2">图片上传:</label> <input type="hidden" name="goodsUrl" id="imgUrl" value="${goods.goodsUrl}"/><!--隐藏域传递图片地址存入数据库--> <div class="formControls col-xs-8 col-sm-9"> <div class="uploader-list-container"> <div class="queueList"> <div id="dndArea" class="placeholder"> <div id="filePicker-2"></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>
js代码:
1 (function( $ ){ 2 // 当domReady的时候开始初始化 3 $(function() { 4 var $wrap = $(\'.uploader-list-container\'), 5 6 // 图片容器 7 $queue = $( \'<ul 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-2\', 144 label: \'点击选择图片\' 145 }, 146 formData: { 147 uid: 123 148 }, 149 dnd: \'#dndArea\', 150 paste: \'#uploader\', 151 swf: \'lib/webuploader/0.1.5/Uploader.swf\', 152 chunked: false, 153 chunkSize: 512 * 1024, 154 server: \'../FileUpload.do\', 155 // runtimeOrder: \'flash\', 156 157 // accept: { 158 // title: \'Images\', 159 // extensions: \'gif,jpg,jpeg,bmp,png\', 160 // mimeTypes: \'image/*\' 161 // }, 162 163 // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。 164 disableGlobalDnd: true, 165 fileNumLimit: 300, 166 fileSizeLimit: 200 * 1024 * 1024, // 200 M 167 fileSingleSizeLimit: 50 * 1024 * 1024 // 50 M 168 }); 169 170 // 拖拽时不接受 js, txt 文件。 171 uploader.on( \'dndAccept\', function( items ) { 172 var denied = false, 173 len = items.length, 174 i = 0, 175 // 修改js类型 176 unAllowed = \'text/plain;application/javascript \'; 177 178 for ( ; i < len; i++ ) { 179 // 如果在列表里面 180 if ( ~unAllowed.indexOf( items[ i ].type ) ) { 181 denied = true; 182 break; 183 } 184 } 185 186 return !denied; 187 }); 188 189 uploader.on(\'dialogOpen\', function() { 190 console.log(\'here\'); 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.on(\'ready\', function() { 210 window.uploader = uploader; 211 }); 212 213 // 当有文件添加进来时执行,负责view的创建 214 function addFile( file ) { 215 var $li = $( \'<li id="\' + file.id + \'">\' + 216 \'<p class="title">\' + file.name + \'</p>\' + 217 \'<p class="imgWrap"></p>\'+ 218 \'<p class="progress"><span></span></p>\' + 219 \'</li>\' ), 220 221 $btns = $(\'<div class="file-panel">\' + 222 \'<span class="cancel">删除</span>\' + 223 \'<span class="rotateRight">向右旋转</span>\' + 224 \'<span class="rotateLeft">向左旋转</span></div>\').appendTo( $li ), 225 $prgress = $li.find(\'p.progress span\'), 226 $wrap = $li.find( \'p.imgWrap\' ), 227 $info = $(\'<p class="error"></p>\'), 228 229 showError = function( code ) { 230 switch( code ) { 231 case \'exceed_size\': 232 text = \'文件大小超出\'; 233 break; 234 235 case \'interrupt\': 236 text = \'上传暂停\'; 237 break; 238 239 default: 240 text = \'上传失败,请重试\'; 241 break; 242 } 243 244 $info.text( text ).appendTo( $li ); 245 }; 246 247 if ( file.getStatus() === \'invalid\' ) { 248 showError( file.statusText ); 249 } else { 250 // @todo lazyload 251 $wrap.text( \'预览中\' ); 252 uploader.makeThumb( file, function( error, src ) { 253 var img; 254 255 if ( error ) { 256 $wrap.text( \'不能预览\' ); 257 return; 258 } 259 260 if( isSupportBase64 ) { 261 img = $(\'<img src="\'+src+\'">\'); 262 $wrap.empty().append( img ); 263 } else { 264 $.ajax(\'lib/webuploader/0.1.5/server/preview.php\', { 265 method: \'POST\', 266 data: src, 267 dataType:\'json\' 268 }).done(function( response ) { 269 if (response.result) { 270 img = $(\'<img src="\'+response.result+\'">\'); 271 $wrap.empty().append( img ); 272 } else { 273 $wrap.text("预览出错"); 274 } 275 }); 276 } 277 }, thumbnailWidth, thumbnailHeight ); 278 279 percentages[ file.id ] = [ file.size, 0 ]; 280 file.rotation = 0; 281 } 282 283 file.on(\'statuschange\', function( cur, prev ) { 284 if ( prev === \'progress\' ) { 285 $prgress.hide().width(0); 286 } else if ( prev === \'queued\' ) { 287 $li.off( \'mouseenter mouseleave\' ); 288 $btns.remove(); 289 } 290 291 // 成功 292 if ( cur === \'error\' || cur === \'invalid\' ) { 293 console.log( file.statusText ); 294 showError( file.statusText ); 295 percentages[ file.id ][ 1 ] = 1; 296 } else if ( cur === \'interrupt\' ) { 297 showError( \'interrupt\' ); 298 } else if ( cur === \'queued\' ) { 299 percentages[ file.id ][ 1 ] = 0; 300 } else if ( cur === \'progress\' ) { 301 $info.remove(); 302 $prgress.css(\'display\', \'block\'); 303 } else if ( cur === \'complete\' ) { 304 $li.append( \'<span class="success"></span>\' ); 305 } 306 307 $li.removeClass( \'state-\' + prev ).addClass( \'state-\' + cur ); 308 }); 309 310 $li.on( \'mouseenter\', function() { 311 $btns.stop().animate({height: 30}); 312 }); 313 314 $li.on( \'mouseleave\', function() { 315 $btns.stop().animate({height: 0}); 316 }); 317 318 $btns.on( \'click\', \'span\', function() { 319 var index = $(this).index(), 320 deg; 321 322 switch ( index ) { 323 case 0: 324 uploader.removeFile( file ); 325 return; 326 327 case 1: 328 file.rotation += 90; 329 break; 330 331 case 2: 332 file.rotation -= 90; 333 break; 334 } 335 336 if ( supportTransition ) { 337 deg = \'rotate(\' + file.rotation + \'deg)\'; 338 $wrap.css({ 339 \'-webkit-transform\': deg, 340 \'-mos-transform\': deg, 341 \'-o-transform\': deg, 342 \'transform\': deg 343 }); 344 } else { 345 $wrap.css( \'filter\', \'progid:DXImageTransform.Microsoft.BasicImage(rotation=\'+ (~~((file.rotation/90)%4 + 4)%4) +\')\'); 346 // use jquery animate to rotation 347 // $({ 348 // rotation: rotation 349 // }).animate({ 350 // rotation: file.rotation 351 // }, { 352 // easing: \'linear\', 353 // step: function( now ) { 354 // now = now * Math.PI / 180; 355 356 // var cos = Math.cos( now ), 357 // sin = Math.sin( now ); 358 359 // $wrap.css( \'filter\', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod=\'auto expand\')"); 360 // } 361 // }); 362 } 363 364 365 }); 366 367 $li.appendTo( $queue ); 368 } 369 370 // 负责view的销毁 371 function removeFile( file ) { 372 var $li = $(\'#\'+file.id); 373 374 delete percentages[ file.id ]; 375 updateTotalProgress(); 376 $li.off().find(\'.file-panel\').off().end().remove(); 377 } 378 379 function updateTotalProgress() { 380 var loaded = 0, 381 total = 0, 382 spans = $progress.children(), 383 percent; 384 385 $.each( percentages, function( k, v ) { 386 total += v[ 0 ]; 387 loaded += v[ 0 ] * v[ 1 ]; 388 } ); 389 390 percent = total ? loaded / total : 0; 391 392 393 spans.eq( 0 ).text( Math.round( percent * 100 ) + \'%\' ); 394 spans.eq( 1 ).css( \'width\', Math.round( percent * 100 ) + \'%\' ); 395 updateStatus(); 396 } 397 398 function updateStatus() { 399 var text = \'\', stats; 400 401 if ( state === \'ready\' ) { 402 text = \'选中\' + fileCount + \'张图片,共\' + 403 WebUploader.formatSize( fileSize ) + \'。\'; 404 } else if ( state === \'confirm\' ) { 405 stats = uploader.getStats(); 406 if ( stats.uploadFailNum ) { 407 text = \'已成功上传\' + stats.successNum+ \'张照片至XX相册,\'+ 408 stats.uploadFailNum + \'张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>\' 409 } 410 411 } else { 412 stats = uploader.getStats(); 413 text = \'共\' + fileCount + \'张(\' + 414 WebUploader.formatSize( fileSize ) + 415 \'),已上传\' + stats.successNum + \'张\'; 416 417 if ( stats.uploadFailNum ) { 418 text += \',失败\' + stats.uploadFailNum + \'张\'; 419 } 420 } 421 422 $info.html( text ); 423 } 424 425 function setState( val ) { 426 var file, stats; 427 428 if ( val === state ) { 429 return; 430 } 431 432 $upload.removeClass( \'state-\' + state ); 433 $upload.addClass( \'state-\' + val ); 434 state = val; 435 436 switch ( state ) { 437 case \'pedding\': 438 $placeHolder.removeClass( \'element-invisible\' ); 439 $queue.hide(); 440 $statusBar.addClass( \'element-invisible\' ); 441 uploader.refresh(); 442 break; 443 444 case \'ready\': 445 $placeHolder.addClass( \'element-invisible\' ); 446 $( \'#filePicker2\' ).removeClass( \'element-invisible\'); 447 $queue.show(); 448 $statusBar.removeClass(\'element-invisible\'); 449 uploader.refresh(); 450 break; 451 452 case \'uploading\': 453 $( \'#filePicker2\' ).addClass( \'element-invisible\' ); 454 $progress.show(); 455 $upload.text( \'暂停上传\' ); 456 break; 457 458 case \'paused\': 459 $progress.show(); 460 $upload.text( \'继续上传\' ); 461 break; 462 463 case \'confirm\': 464 $progress.hide(); 465 $( \'#filePicker2\' ).removeClass( \'element-invisible\' ); 466 $upload.text( \'开始上传\' ); 467 468 stats = uploader.getStats(); 469 if ( stats.successNum && !stats.uploadFailNum ) { 470 setState( \'finish\' ); 471 return; 472 } 473 break; 474 case \'finish\': 475 stats = uploader.getStats(); 476 if ( stats.successNum ) { 477 alert( \'上传成功\' ); 478 } else { 479 // 没有成功的图片,重设 480 state = \'done\'; 481 location.reload(); 482 } 483 break; 484 } 485 486 updateStatus(); 487 } 488 489 uploader.onUploadProgress = function( file, percentage ) { 490 var $li = $(\'#\'+file.id), 491 $percent = $li.find(\'.progress span\'); 492 493 $percent.css( \'width\', percentage * 100 + \'%\' ); 494 percentages[ file.id ][ 1 ] = percentage; 495 updateTotalProgress(); 496 }; 497 498 uploader.onFileQueued = function( file ) { 499 fileCount++; 500 fileSize += file.size; 501 502 if ( fileCount === 1 ) { 503 $placeHolder.addClass( \'element-invisible\' ); 504 $statusBar.show(); 505 } 506 507 addFile( file ); 508 setState( \'ready\' ); 509 updateTotalProgress(); 510 }; 511 512 uploader.onFileDequeued = function( file ) { 513 fileCount--; 514 fileSize -= file.size; 515 516 if ( !fileCount ) { 517 setState( \'pedding\' ); 518 } 519 520 removeFile( file ); 521 updateTotalProgress(); 522 523 }; 524 525 //在上传完成之前客户端询问服务器上传是否成功 526 uploader.on( \'uploadAccept\', function( file, response) { 527 var obj = eval(response); 528 //alert(obj.state+"--"+obj.filePath); 529 if(obj.state=="NO"){ 530 return false; 531 } 532 $("#imgUrl").val(obj.filePath); 533 //alert($("#imgUrl").val()); 534 }); 535 uploader.on( \'all\', function( type ) { 536 var stats; 537 switch( type ) { 538 case \'uploadFinished\': 539 setState( \'confirm\' ); 540 break; 541 542 case \'startUpload\': 543 setState( \'uploading\' ); 544 break; 545 546 case \'stopUpload\': 547 setState( \'paused\' ); 548 break; 549 550 } 551 }); 552 553 uploader.onError = function( code ) { 554 alert( \'Eroor: \' + code ); 555 }; 556 557 $upload.on(\'click\', function() { 558 if ( $(this).hasClass( \'disabled\' ) ) { 559 return false; 560 } 561 562 if ( state === \'ready\' ) { 563 uploader.upload(); 564 } else if ( state === \'paused\' ) { 565 uploader.upload(); 566 } else if ( state === \'uploading\' ) { 567 uploader.stop(); 568 } 569 }); 570 571 $info.on( \'click\', \'.retry\', function() { 572 uploader.retry(); 573 } ); 574 575 $info.on( \'click\', \'.ignore\', function() { 576 alert( \'todo\' ); 577 } ); 578 579 $upload.addClass( \'state-\' + state ); 580 updateTotalProgress(); 581 }); 582 583 })( jQuery );
后台实现:
1 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 System.out.println("开始上传"); 3 resp.setCharacterEncoding("utf-8"); 4 //设置上传文件保存的路径 5 String filePath = req.getSession().getServletContext().getRealPath("/")+"images"; 6 //System.out.println(filePath); 7 File file = new File(filePath); 8 if(!file.exists()){ 9 file.mkdirs(); 10 } 11 12 SmartUpload su = new SmartUpload(); 13 //初始化smartupload 14 su.initialize(getServletConfig(), req, resp); 15 //设置文件的大小 16 su.setMaxFileSize(1024*1024*10); 17 //设置所有文件的大小 18 su.setTotalMaxFileSize(1024*1024*100); 19 //设置允许上传的文件类型 20 su.setAllowedFilesList("jpg,png,gif"); 21 //设置禁止上传的文件类型 22 JSONObject json = new JSONObject(); 23 try { 24 su.setDeniedFilesList("rar,zip,jsp,js"); 25 su.upload(); 26 int count = su.save(filePath); 27 String filepath = "../images/"+ su.getFiles().getFile(0).getFileName(); 28 if(count>0){ 29 json.put("state", "OK"); 30 json.put("filePath", filepath); 31 } 32 else{ 33 json.put("state", "NO"); 34 } 35 //System.out.println(json.toString()); 36 resp.getWriter().write(json.toString()); 37 //System.out.println("上传成功"+count+"个文件!"); 38 } catch (Exception e) { 39 e.printStackTrace(); 40 } 41 } 42 }
至此上传文件到服务器指定目录并返回文件地址赋给隐藏input 的value,最后提交表单存入数据库。功能已基本实现,后续扩展自己研究。