首页 > 代码库 > 文件上传插件WebUploader的使用

文件上传插件WebUploader的使用

插件描述:

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

插件特点:

分片、并发
分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。
当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。

预览、压缩
支持常用图片格式jpg,jpeg,gif,bmp,png预览与压缩,节省网络数据传输。
解析jpeg中的meta信息,对于各种orientation做了正确的处理,同时压缩后上传保留图片的所有原始meta数据。

多途径添加文件
支持文件多选,类型过滤,拖拽(文件&文件夹),图片粘贴功能。
粘贴功能主要体现在当有图片数据在剪切板中时(截屏工具如QQ(Ctrl + ALT + A), 网页中右击图片点击复制),Ctrl + V便可添加此图片文件。

HTML5 & FLASH
兼容主流浏览器,接口一致,实现了两套运行时支持,用户无需关心内部用了什么内核。
同时Flash部分没有做任何UI相关的工作,方便不关心flash的用户扩展和自定义业务需求。

MD5秒传
当文件体积大、量比较多时,支持上传前做文件md5值验证,一致则可直接跳过。
如果服务端与前端统一修改算法,取段md5,可大大提升验证性能,耗时在20ms左右。

易扩展、可拆分
采用可拆分机制, 将各个功能独立成了小组件,可自由搭配。
采用AMD规范组织代码,清晰明了,方便高级玩家扩展。

资源介绍:

技术分享

// SWF文件,当使用Flash运行时需要引入。
Uploader.swf
// 完全版本。
webuploader.js
webuploader.min.js
// 只有Flash实现的版本。
webuploader.flashonly.js
webuploader.flashonly.min.js
// 只有Html5实现的版本。
webuploader.html5only.js
webuploader.html5only.min.js
// 去除图片处理的版本,包括HTML5和FLASH.
webuploader.withoutimage.js
webuploader.withoutimage.min.js

使用方法:

可以参考  WebUploader API文档  http://fex.baidu.com/webuploader/doc/

接下来以图片上传实例,讲解如何使用WebUploader。

我们首先将css和相关js文件加载。

1 <link rel="stylesheet" type="text/css" href="css/webuploader.css">
2 <script src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
3 <script type="text/javascript" src="js/webuploader.min.js"></script> 

然后我们需要准备一个按钮#imgPicker,和一个用来存放添加的文件信息列表的容器#fileList,在body中加入如下代码:

1 <div id="uploadimg">   
2     <div id="fileList" class="uploader-list"></div>   
3     <div id="imgPicker">选择图片</div>  
4 </div>

首先创建Web Uploader实例:

 1 var uploader = WebUploader.create({   
 2     auto: true, // 选完文件后,是否自动上传   
 3     swf: ‘js/Uploader.swf‘, // swf文件路径   
 4     server: ‘/uploadServlet?methodName=fileupload‘, // 文件接收服务端   
 5     pick: ‘#imgPicker‘, // 选择文件的按钮。可选   
 6     // 只允许选择图片文件。   
 7     accept: {   
 8         title: ‘Images‘,   
 9         extensions: ‘gif,jpg,jpeg,bmp,png‘,   
10         mimeTypes: ‘image/*‘  
11     }  
12 }); 

接着监听fileQueued事件,即当有文件添加进来的时候,通过uploader.makeThumb来创建图片预览图。

 1 uploader.on( ‘fileQueued‘, function( file ) {   
 2     var $list = $("#fileList"), //获取文件列表 
 3     $li = $(
 4         ‘<div id="‘ + file.id + ‘" class="file-item thumbnail">‘ +   
 5         ‘<img>‘ +   
 6         ‘<div class="info">‘ + file.name + ‘</div>‘ +   
 7         ‘</div>‘
 8     ),   
 9     $img = $li.find(‘img‘);
10     $list.append( $li ); // $list为容器jQuery实例    
11     // 创建缩略图   
12     uploader.makeThumb( file, function( error, src ) {   
13         if ( error ) {   
14             $img.replaceWith(‘<span>不能预览</span>‘);   
15             return;   
16         }      
17         $img.attr( ‘src‘, src );//设置预览图
18     }, 100, 100 ); //100x100为缩略图尺寸  
19 }); 

最后是上传状态提示了:
文件上传过程中对应uploadProgress事件。

 1 // 文件上传过程中创建进度条实时显示。
 2 uploader.on( ‘uploadProgress‘, function( file, percentage ) {   
 3     var $li = $( ‘#‘+file.id ),   
 4     $percent = $li.find(‘.progress span‘);      
 5     //避免重复创建   
 6     if ( !$percent.length ) {   
 7         $percent = $(‘<p class="progress"><span></span></p>‘).appendTo( $li ).find(‘span‘);   
 8     }
 9     $percent.css( ‘width‘, percentage * 100 + ‘%‘ );  
10 });

文件上传成功对应uploadSuccess事件。

1 // 文件上传成功,给item添加成功class, 用样式标记上传成功。  
2 uploader.on( ‘uploadSuccess‘, function( file, res ) {
3     console.log(res.filePath);//这里可以得到上传后的文件路径
4     $( ‘#‘+file.id ).addClass(‘upload-state-done‘);  
5 }); 

文件上传失败对应uploadError事件。

 1 // 文件上传失败,显示上传出错。 
 2 uploader.on( ‘uploadError‘, function( file ) {   
 3     var $li = $( ‘#‘+file.id ),   
 4     $error = $li.find(‘div.error‘);      
 5     // 避免重复创建   
 6     if ( !$error.length ) {   
 7         $error = $(‘<div class="error"></div>‘).appendTo( $li );   
 8     }     
 9     $error.text(‘上传失败‘);  
10 });

文件上传完成对应uploadComplete事件。

1 // 完成上传,成功或者失败,先删除进度条。
2 uploader.on( ‘uploadComplete‘, function( file ) {   
3     $( ‘#‘+file.id ).find(‘.progress‘).remove();  
4 });

到这里,我们就实现了一个简单的图片上传实例,点击“选择图片”会弹出文件选择对话框,当选择图片后,即进入上传图片流程,会将图片对应的缩略图现实在列表里。

接下来贴上文件的分片上传代码:

稍等,没整理呢。。。

 1 public void fileUpload(HttpServletRequest request,HttpServletResponse response) throws ServletException {
 2     try {
 3         String path = request.getParameter("path");
 4         path = path != null ? java.net.URLDecoder.decode(path, "utf-8"): "";
 5         boolean isMultipart = ServletFileUpload.isMultipartContent(request);
 6 
 7         if (isMultipart) {
 8         FileItemFactory factory = new DiskFileItemFactory();
 9         ServletFileUpload upload = new ServletFileUpload(factory);
10 
11         // 得到所有的表单域,它们目前都被当作FileItem
12         List<FileItem> fileItems = upload.parseRequest(request);
13 
14         String id = "";
15         String fileName = "";
16         // 如果大于1说明是分片处理
17         int chunks = 1;
18         int chunk = 0;
19         FileItem tempFileItem = null;
20 
21         for (FileItem fileItem : fileItems) {
22             if (fileItem.getFieldName().equals("id")) {
23             id = fileItem.getString();
24             } else if (fileItem.getFieldName().equals("name")) {
25             fileName = new String(fileItem.getString().getBytes("ISO-8859-1"), "UTF-8");
26             } else if (fileItem.getFieldName().equals("chunks")) {
27             chunks = NumberUtils.toInt(fileItem.getString());
28             } else if (fileItem.getFieldName().equals("chunk")) {
29             chunk = NumberUtils.toInt(fileItem.getString());
30             } else if (fileItem.getFieldName().equals("file")) {
31             tempFileItem = fileItem;
32             }
33         }
34 
35         // 临时目录用来存放所有分片文件
36         String tempFileDir = getTempFilePath()+ File.separator + id;
37         File parentFileDir = new File(tempFileDir);
38         if (!parentFileDir.exists()) {
39             parentFileDir.mkdirs();
40         }
41         // 分片处理时,前台会多次调用上传接口,每次都会上传文件的一部分到后台(默认每片为5M)
42         File tempPartFile = new File(parentFileDir, fileName + "_" + chunk + ".part");
43         FileUtils.copyInputStreamToFile(tempFileItem.getInputStream(),tempPartFile);
44 
45         // 是否全部上传完成
46         // 所有分片都存在才说明整个文件上传完成
47         boolean uploadDone = true;
48         for (int i = 0; i < chunks; i++) {
49             File partFile = new File(parentFileDir, fileName + "_" + i + ".part");
50             if (!partFile.exists()) {
51             uploadDone = false;
52             }
53         }
54         // 所有分片文件都上传完成
55         // 将所有分片文件合并到一个文件中
56         if (uploadDone) {
57             File destTempFile = new File(getTempFilePath(), fileName);
58             for (int i = 0; i < chunks; i++) {
59             File partFile = new File(parentFileDir, fileName + "_" + i + ".part");
60 
61             FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
62 
63             FileUtils.copyFile(partFile, destTempfos);
64 
65             destTempfos.close();
66             }
67             // 得到 destTempFile 就是最终的文件
68             // 添加到文件系统或者存储中
69              
70             // 删除临时目录中的分片文件
71             FileUtils.deleteDirectory(parentFileDir);
72             // 删除临时文件
73             destTempFile.delete();
74              
75             ResponseUtil.responseSuccess(response, null);
76         } else {
77             // 临时文件创建失败
78             if (chunk == chunks -1) {
79             FileUtils.deleteDirectory(parentFileDir);
80             ResponseUtil.responseFail(response, "500", "内部错误");
81             }
82         }
83         }
84     } catch (Exception e) {
85         logger.error(e.getMessage(), e);
86         ResponseUtil.responseFail(response, "500", "内部错误");
87     }
88 }

 

文件上传插件WebUploader的使用