plupload上传插件在SpringMVC中的整合

前言:最近在给学院的网站做一个添加附件的功能,首先到了某某邮箱看了一下,简单实用,但是是flash做的,无法拷贝,就只好上网找插件了。经过筛选,终于找到plupload这款插件(事实上有的编辑器自带添加附件功能)。官网只有PHP版本,后来各种百度谷歌,找到的资料都用点小问题,拼搏一天终于实现了功能,下面就把遇到的问题和重点部分写出来,希望遇到同样问题的同学可以参考。

首先你需要下载plupload插件,下载地址:http://www.plupload.com/download/

JSP页面配置如下:

[java] view plaincopy

  1. <!-- 配置界面上的css -->
  2. <link rel="stylesheet" type="text/css" href="<%=basePath%>plupload/js/jquery.plupload.queue/css/jquery.plupload.queue.css">
  3. <script type="text/javascript" src="<%=basePath%>js/jquery-1.9.1.min.js"></script>
  4. <script type="text/javascript" src="<%=basePath%>plupload/js/plupload.full.min.js"></script>
  5. <script type="text/javascript" src="<%=basePath%>plupload/js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
  6. <!-- 国际化中文支持 -->
  7. <script type="text/javascript" src="<%=basePath%>plupload/js/i18n/zh_CN.js"></script>
  8. <script type="text/javascript">
  9. // Initialize the widget when the DOM is ready
  10. $(function() {
  11. // Setup html5 version
  12. function plupload(){
  13. $("#uploader").pluploadQueue({
  14. // General settings
  15. runtimes : ‘flash,html5,gears,browserplus,silverlight,html4‘,
  16. url : "<%=basePath%>upload",
  17. //unique_names: true,
  18. chunk_size : ‘1mb‘,
  19. //rename : true,
  20. dragdrop: true,
  21. filters : {
  22. // Maximum file size
  23. max_file_size : ‘10mb‘,
  24. // Specify what files to browse for
  25. mime_types: [
  26. {title : "Image files", extensions : "jpg,gif,png"},
  27. {title : "Zip files", extensions : "zip"}
  28. ]
  29. },
  30. // Resize images on clientside if we can
  31. resize: {
  32. width : 200,
  33. height : 200,
  34. quality : 90,
  35. crop: true
  36. // crop to exact dimensions
  37. },             // Flash settings
  38. flash_swf_url : ‘<%=basePath%>plupload/js/Moxie.swf‘,
  39. // Silverlight settings
  40. silverlight_xap_url : ‘<%=basePath%>plupload/js/Moxie.xap‘ ,
  41. // 参数
  42. multipart_params: {‘user‘: ‘Rocky‘, ‘time‘: ‘2012-06-12‘}
  43. });
  44. }
  45. plupload();
  46. $(‘#Reload‘).click(function(){
  47. plupload();
  48. });
  49. });
  50. </script>
  51. <div style="width:750px; margin:0px auto;">
  52. <div id="uploader">
  53. <p>您的浏览器未安装 Flash, Silverlight, Gears, BrowserPlus 或者支持 HTML5 .</p>
  54. </div>
  55. <input value="继续上传" id="Reload" type="button">
  56. </div>

JS部分配置说明可以参考:http://www.douban.com/note/188007146/ 和 http://www.aixueit.com/thread-304-1-1.html,详细配置请自行百度或者查阅官网http://www.plupload.com。界面如下:

重点的就是后台了,在写后台前不得不说明一下plupload的大概工作原理:如果上传列表中存在文件大小大于chunk_size但是小于max_file_size的文件,那么plupload会将其分解成最大大小为chunk_size的几个小块(这可以绕过服务器设置的限制最大上传文件大小,另外进度条也会显示的合理),然后再将文件中的各个文件(包括分解后的小块)依次上传,这里的上传并不是一次性全部传给服务器,而是当一个文件上传完成后,再上传第二个文件,这样也很好的做了进度条的显示。当然了,在后台代码中,如果遇到分块的文件,必须对其进行合并。

先附上之前找的部分资料吧,http://www.rockydo.com/articleDetail.php?id=83  感觉挺好的,不过我使用commons-fileupload-1.2.2.jar方式上传的时候获取不到值(能实现的同学欢迎告诉我),所以后来就只好换种方式了,于是就看到了这篇文章http://stackoverflow.com/questions/16813907/apache-commons-file-upload-with-spring-mvc-and-plupload,使用MultiparFile方式上传,代码剪短,但是给了我不小的启发。好了,开始写我的思路吧。

为了更清楚的表达结构,我决定将重点处理代码写入一个PluploadUtil工具类,在配上一个Plupload Bean类,这样在调用时就方便多了。具体代码如下:

[java] view plaincopy

  1. import java.io.BufferedOutputStream;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.util.Iterator;
  8. import java.util.List;
  9. import org.springframework.util.MultiValueMap;
  10. import org.springframework.web.multipart.MultipartFile;
  11. import org.springframework.web.multipart.MultipartHttpServletRequest;
  12. /**
  13. * Plupload是一个上传插件。
  14. * 上传原理为单个文件依次发送至服务器.
  15. * 上传打文件时可以将其碎片化上传。但是一般情况下,不会这样做,
  16. * 所以这里更多的是处理普通文件的批量上传。
  17. * 这里主要处理文件上传
  18. */
  19. public class PluploadUtil {
  20. private static final int BUF_SIZE = 2 * 1024;
  21. /**上传失败响应的成功状态码*/
  22. public static final String RESP_SUCCESS = "{\"jsonrpc\" : \"2.0\", \"result\" : \"success\", \"id\" : \"id\"}";
  23. /**上传失败响应的失败状态码*/
  24. public static final String RESP_ERROR = "{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}";
  25. /**
  26. * 用于Plupload插件的文件上传,自动生成唯一的文件保存名
  27. * @param plupload - 存放上传所需参数的bean
  28. * @param dir - 保存目标文件目录
  29. * @throws IllegalStateException
  30. * @throws IOException
  31. */
  32. public static void upload(Plupload plupload, File dir) throws IllegalStateException, IOException {
  33. //生成唯一的文件名
  34. String filename = "" + System.currentTimeMillis() + plupload.getName();
  35. upload(plupload, dir, filename);
  36. }
  37. /**
  38. * 用于Plupload插件的文件上传
  39. * @param plupload - 存放上传所需参数的bean
  40. * @param dir - 保存目标文件目录
  41. * @param filename - 保存的文件名
  42. * @throws IllegalStateException
  43. * @throws IOException
  44. */
  45. public static void upload(Plupload plupload, File dir, String filename) throws IllegalStateException, IOException {
  46. int chunks = plupload.getChunks();  //获取总的碎片数
  47. int chunk = plupload.getChunk();    //获取当前碎片(从0开始计数)
  48. System.out.println(plupload.getMultipartFile() + "----------");
  49. MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) plupload.getRequest();
  50. MultiValueMap<String, MultipartFile> map = multipartRequest.getMultiFileMap();
  51. if(map != null) {
  52. if (!dir.exists()) dir.mkdirs();    //如果目标文件夹不存在则创建新的文件夹
  53. //事实上迭代器中只存在一个值,所以只需要返回一个值即可
  54. Iterator<String> iter = map.keySet().iterator();
  55. while(iter.hasNext()) {
  56. String str = (String) iter.next();
  57. List<MultipartFile> fileList =  map.get(str);
  58. for(MultipartFile multipartFile : fileList) {
  59. //因为只存在一个值,所以最后返回的既是第一个也是最后一个值
  60. plupload.setMultipartFile(multipartFile);
  61. //创建新目标文件
  62. File targetFile = new File(dir.getPath()+ "/" + filename);
  63. //当chunks>1则说明当前传的文件为一块碎片,需要合并
  64. if (chunks > 1) {
  65. //需要创建临时文件名,最后再更改名称
  66. File tempFile = new File(dir.getPath()+ "/" + multipartFile.getName());
  67. //如果chunk==0,则代表第一块碎片,不需要合并
  68. saveUploadFile(multipartFile.getInputStream(), tempFile, chunk == 0 ? false : true);
  69. //上传并合并完成,则将临时名称更改为指定名称
  70. if (chunks - chunk == 1) {
  71. tempFile.renameTo(targetFile);
  72. }
  73. } else {
  74. //否则直接将文件内容拷贝至新文件
  75. multipartFile.transferTo(targetFile);
  76. }
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * 保存上传文件,兼合并功能
  83. */
  84. private static void saveUploadFile(InputStream input, File targetFile, boolean append) throws IOException {
  85. OutputStream out = null;
  86. try {
  87. if (targetFile.exists() && append) {
  88. out = new BufferedOutputStream(new FileOutputStream(targetFile, true), BUF_SIZE);
  89. } else {
  90. out = new BufferedOutputStream(new FileOutputStream(targetFile), BUF_SIZE);
  91. }
  92. byte[] buffer = new byte[BUF_SIZE];
  93. int len = 0;
  94. //写入文件
  95. while ((len = input.read(buffer)) > 0) {
  96. out.write(buffer, 0, len);
  97. }
  98. } catch (IOException e) {
  99. throw e;
  100. } finally {
  101. //关闭输入输出流
  102. if (null != input) {
  103. try {
  104. input.close();
  105. } catch (IOException e) {
  106. e.printStackTrace();
  107. }
  108. }
  109. if (null != out) {
  110. try {
  111. out.close();
  112. } catch (IOException e) {
  113. e.printStackTrace();
  114. }
  115. }
  116. }
  117. }
  118. /**
  119. * 判断是否全部上传完成
  120. * 碎片需合并后才返回真
  121. */
  122. public static boolean isUploadFinish(Plupload plupload) {
  123. return (plupload.getChunks() - plupload.getChunk() == 1);
  124. }
  125. }

[java] view plaincopy

  1. import javax.servlet.http.HttpServletRequest;
  2. import org.springframework.web.multipart.MultipartFile;
  3. /**
  4. * Plupload是一个上传插件。
  5. * 这是一个bean类,主要存储Plupload插件上传时需要的参数。
  6. * 属性名不可随意改动.
  7. * 这里主要使用MultipartFile文件上传方法
  8. */
  9. public class Plupload {
  10. /**文件临时名(打文件被分解时)或原名*/
  11. private String name;
  12. /**总的块数*/
  13. private int chunks = -1;
  14. /**当前块数(从0开始计数)*/
  15. private int chunk = -1;
  16. /**HttpServletRequest对象,不能直接传入进来,需要手动传入*/
  17. private HttpServletRequest request;
  18. /**保存文件上传信息,不能直接传入进来,需要手动传入*/
  19. private MultipartFile multipartFile;
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public int getChunks() {
  27. return chunks;
  28. }
  29. public void setChunks(int chunks) {
  30. this.chunks = chunks;
  31. }
  32. public int getChunk() {
  33. return chunk;
  34. }
  35. public void setChunk(int chunk) {
  36. this.chunk = chunk;
  37. }
  38. public HttpServletRequest getRequest() {
  39. return request;
  40. }
  41. public void setRequest(HttpServletRequest request) {
  42. this.request = request;
  43. }
  44. public MultipartFile getMultipartFile() {
  45. return multipartFile;
  46. }
  47. public void setMultipartFile(MultipartFile multipartFile) {
  48. this.multipartFile = multipartFile;
  49. }
  50. }

最后就是测试类了,这部分不是重点,比较粗糙

[java] view plaincopy

  1. import java.io.File;
  2. import java.io.IOException;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. @Controller
  9. public class uploadAction {
  10. public static final String FileDir = "uploadfile/";
  11. /**上传界面*/
  12. @RequestMapping("/uploadui")
  13. public String uploadUI() {
  14. return "login.upload";
  15. }
  16. /**上传处理方法*/
  17. @RequestMapping(value="/upload", method = RequestMethod.POST)
  18. public String upload(Plupload plupload,HttpServletRequest request, HttpServletResponse response) {
  19. //System.out.println(plupload.getChunk() + "===" + plupload.getName() + "---" + plupload.getChunks());
  20. plupload.setRequest(request);
  21. //文件存储路径
  22. File dir = new File(plupload.getRequest().getSession().getServletContext().getRealPath("/") + FileDir);
  23. System.out.println(dir.getPath());
  24. try {
  25. //上传文件
  26. PluploadUtil.upload(plupload, dir);
  27. //判断文件是否上传成功(被分成块的文件是否全部上传完成)
  28. if (PluploadUtil.isUploadFinish(plupload)) {
  29. System.out.println(plupload.getName() + "----");
  30. }
  31. } catch (IllegalStateException e) {
  32. // TODO Auto-generated catch block
  33. e.printStackTrace();
  34. } catch (IOException e) {
  35. // TODO Auto-generated catch block
  36. e.printStackTrace();
  37. }
  38. return "login.upload";
  39. }
  40. }

好了,到此重点部分的工作算是完成了,需要提醒一下的就是,在前台JS部分有一个rename参数,如果设置成true,后台就获取不到文件的真实名称了,后台获取真实名称也不在是MultipartFile的getOriginalFilename()方法了,因为被分块的文件名称会改变,而需要使用Plupload.getName()获取。

附上上传成功界面图(这里把设置的文件是没有限制):

至于后面的如何将状态码以JOSN形式返回与前台进行交互和文件大小一次性上传大小的限制,就在往后用到了在详述吧。

以上观点均为个人意见,欢迎指正与批评。

时间: 2024-08-02 16:24:35

plupload上传插件在SpringMVC中的整合的相关文章

Plupload 上传插件 使用指南 (二)jquery

项目中用到改上传插件,因此抽了一晚上事件把列子和文档看了一下,翻译过来,如有错误的翻译请帮助我一起纠正谢谢. 介绍: Plupload是有TinyMCE的开发者开发的,为您的内容管理系统或是类似上传程序提供一个高度可用的上传插件.Plupload 目前分为一个核心API 和一个jQuery上传队列部件,这样使你可以直接使用或是自己定制. 特性: 注释:1.gears:http://zh.wikipedia.org/wiki/Gears 2.Silverlight:http://zh.wikipe

plupload上传插件绑定事件的两种方法

在经受一天的磨难之后终于找到处理事件方法: 先引用: <script src="js/plupload.full.min.js" type="text/javascript"></script><!--必需引入--> <script src="js/i18n/zh_CN.js" type="text/javascript"></script><!--显示中文--

Plupload 上传插件 使用指南 jquery

Plupload是一款由著名的web编辑器TinyMCE团队开发的上传组件,简单易用且功能强大,我们完全可以使用Plupload来代替以前的SWFUpload. Plupload有以下功能和特点: 1.拥有多种上传方式:HTML5.flash.silverlight以及传统的<input type=”file” />.Plupload会自动侦测当前的环境,选择最合适的上传方式,并且会优先使用HTML5的方式.所以你完全不用去操心当前的浏览器支持哪些 上传方式,Plupload会自动为你选择最合

关于Plupload结合上传插件jquery.plupload.queue的使用

方便日后查阅!! 事例代码: @import url(common/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css) ; src="http://www.iadpush.com/assets/common/jquery-1.8.2.min.js"> src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"> src="

文件上传插件Uploadify在Struts2中的应用,完整详细实例

->最近由于项目需要使用到一个上传插件,在网上发现uploadify挺不错,所以决定使用它,但是官网文档和例子是php的,而项目是SSI框架的,所以自己对uploadify在struts2中的使用进行了一番研究,最终实现了.发现网上关于这方面的资料很少,而且有的一两篇例子还不大全,网友提问质疑很多,所以,下面我特将我的代码公布: --------------------------------------------------------------------- 步骤一: 到官网上下载upl

Jquery 上传插件 FineUploader 在 webform 和 mvc 中的使用;

  多文件上传组件FineUploader使用心得 FineUploader 结合 一般处理程序 [上传示例] 参考:http://www.cnblogs.com/dudu/archive/2012/11/27/fine_uploader_mvc_ajax.html  asp.net mvc示例 参考 :http://www.cnblogs.com/chenkai/archive/2013/01/04/2844702.html  http://www.cnblogs.com/guero/p/38

Aps.net中基于bootstrapt图片上传插件的应用

Aps.net中基于bootstrapt图片上传插件的应用 在最近的项目中需要使用一个图片上传的功能,而且是多张图片同时上传到服务器的文件夹中,将图片路径存放在数据库中.为了外观好看使用了bootstrapt插件.插件下载地址:   http://www.jq22.com/jquery-info5231 index.html中的代码: <script> //初始化函数 $("#file-1").fileinput({ uploadUrl: 'image/Handler.as

7 款基于 JavaScript/AJAX 的文件上传插件

本文整理了7款基于JavaScript和AJAX的文件上传插件,这些插件基本上都能实现以下功能: 多文件上传 拖拽操作 实时上传进度 自定义上传限制 希望能为你的开发工作带来帮助. 1.  jQuery File Upload 具有多文件上传.拖拽.进度条和图像预览功能的文件上传插件,支持跨域.分块.暂停恢复和客户端图像缩放.可与任何服务端平台(如PHP.Python.Ruby on Rails.Java.Node.js.Go等)一起使用,支持标准的HTML表单文件上传. 2.  Pixelco

7款js文件上传插件

1.  jQuery File Upload 具有多文件上传.拖拽.进度条和图像预览功能的文件上传插件,支持跨域.分块.暂停恢复和客户端图像缩放.可与任何服务端平台(如PHP.Python.Ruby on Rails.Java.Node.js.Go等)一起使用,支持标准的HTML表单文件上传. 2.  Pixelcone Fileuploader 使用HTML5 API的jQuery文件上传插件,支持AJAX上传和拖拽操作,以及针对老版本浏览器的iframe上传部件.有多种形式来实现多文件上传,