弄了好久终于把 这两个组件给弄清楚了,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 );
upload.js
后台实现:
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,最后提交表单存入数据库。功能已基本实现,后续扩展自己研究。