使用plupload做一个类似qq邮箱附件上传的效果
公司项目中使用的框架是springmvc+hibernate+spring,目前需要做一个类似qq邮箱附件上传的功能,暂时只是上传小类型的附件
处理过程和解决方案都需要添加附件,处理过程和解决方案都可以添加多个附件,也可一个都不添加
以其中一个为例:(文件保存到了数据库中),有关plupload的内容可参考:http://www.360doc.com/content/14/0714/03/552866_394228686.shtml
首先是po
package cn.com.plupload.po; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * 附件 和处理过程多对一 * @author GoodLuck * */ @Entity @Table(name="annex",catalog="itac") public class Annex { @Id @Column(name="id") @GenericGenerator(name="generator",strategy="increment") private Long id; /** * 上传文件名称 */ @Column(name="realName") private String realName; /** * 上传文件内容 */ @Column(name="fileContent") private byte[] fileContent; /** * 处理人id,本例中可以忽略 */ @Column(name="handId") private Long handId; /** * 客户id */ @Column(name="customerId") private Long customerId; /** * 外键列,此外键可能对应处理过程表,也可能对应的事解决方案表 */ @Column(name="foreign_id") private Long foreignId; //getter and setter }
dao层
package cn.com.plupload.dao; import java.util.List; import javax.annotation.Resource; import org.hibernate.SessionFactory; import org.springframework.orm.hibernate4.support.HibernateDaoSupport; import org.springframework.stereotype.Repository; import cn.com.plupload.po.Annex; /** * 方法很简单,注释就忽略掉了 * @author GoodLuck * */ @Repository public class AnnexDao extends HibernateDaoSupport{ @Resource public void set(SessionFactory sessionFactory){ this.setSessionFactory(sessionFactory); } public Long insertAnnex(Annex annex){ return (Long) this.getHibernateTemplate().save(annex); } public Long getMaxId(){ List l = this.getHibernateTemplate().find("select max(id) from Annex"); ); } public void deleteAnnex(Annex annex){ this.getHibernateTemplate().delete(annex); } }
service层
package cn.com.plupload.service; import javax.annotation.Resource; import javax.transaction.Transactional; import org.springframework.stereotype.Service; import cn.com.plupload.dao.AnnexDao; import cn.com.plupload.po.Annex; /** * 注释忽略 * @author GoodLuck * */ @Service public class AnnexService { @Resource private AnnexDao annexDao; @Transactional public Long saveAnnex(Annex annex){ return this.annexDao.insertAnnex(annex); } @Transactional public Long getMaxId(){ return this.annexDao.getMaxId(); } @Transactional public void deleteAnnex(Annex annex){ this.annexDao.deleteAnnex(annex); } }
controller层
package cn.com.plupload.controller; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.google.gson.Gson; import cn.com.plupload.po.Annex; import cn.com.plupload.service.AnnexService; @Controller public class AnnexController { @Resource private AnnexService annexService; /** * 跳转到上传文件页面 * @return */ @RequestMapping("toUploadPage") public String toUploadPage(){ return "upload/upload"; } @RequestMapping("doTest") public String doTest(){ System.out.println("in"); return null; } @RequestMapping("uploadAnnex") public void upload(@RequestParam("file") MultipartFile file, String annexStr, HttpServletResponse response) { /** * 如果annexStr为null,则设置为"" */ annexStr=annexStr==null?"":annexStr; StringBuffer sb = new StringBuffer(); InputStream is; try { Long maxId = this.annexService.getMaxId(); maxId=maxId==:maxId; is = file.getInputStream(); byte[] buffer = this.inputStrean2ByteArr(is); Annex annex = new Annex(); annex.setId(maxId+); annex.setCustomerId(1L); annex.setFileContent(buffer); annex.setHandId(1L); annex.setRealName(file.getOriginalFilename()); Long annexId = this.annexService.saveAnnex(annex); /** * 将当前的附件的id和name以id*name的形式发送到前台,如果有多个附件,则最后的形式就是|id*name}id*name格式 * 第一个|可以在前台做一下处理,则,后台接收的时候,就不用再去截取去掉第一个| */ sb.append(annexStr + "|" + annexId + "*" + file.getOriginalFilename()); response.getWriter().write(sb.toString()); } catch (IOException e) { e.printStackTrace(); } } private byte[] inputStrean2ByteArr(InputStream inStream) throws IOException { ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); ]; ; , )) > ) { swapStream.write(buff, , rc); } byte[] in2b = swapStream.toByteArray(); return in2b; } @ResponseBody @RequestMapping("deleteAnnex") public String deleteAnnex(Long annexId){ Gson gson = new Gson(); try{ Annex annex = new Annex(); annex.setId(annexId); this.annexService.deleteAnnex(annex); return gson.toJson("success"); }catch(Exception e){ return gson.toJson("fail"); } } }
页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="${pageContext.request.contextPath }/resources/js/jquery-1.11.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath }/resources/js/plupload.full.min.js"></script> </head> <body style="font: 13px Verdana; background: #eee; color: #333"> <a id="pickfiles" href="javascript:;">[选择文件]</a> <div id="container"> </div> <br /> <div id="filelist">Your browser doesn't have Flash, Silverlight or HTML5 support.</div> <br /> <pre id="console"></pre> <form> <div id="hiddenStr"></div> </form> <div id="zifuchuan"></div> <script type="text/javascript"> var idName = ""; var uploader = new plupload.Uploader( { runtimes : 'html5,flash,silverlight,html4', browse_button : 'pickfiles', // you can pass in id... container : document.getElementById('container'), // ... or DOM Element itself url : '<c:url value="/uploadAnnex"/>', flash_swf_url : '<c:url value="/resources/other/Moxie.swf"/>', silverlight_xap_url : '<c:url value="/resources/other/Moxie.xap"/>', filters : { max_file_size : '10mb', mime_types : [ { title : "Image files", extensions : "jpg,gif,png" }, { title : "Zip files", extensions : "zip,rar" } ] }, init : { PostInit : function() { document.getElementById('filelist').innerHTML = ''; }, FilesAdded : function(up, files) {//参数files为列队中的所有文件 //本例中,当添加了文件,就会自动上传,不需要点击额外的按钮,文件完成之后会生成一个input,旧的input就是去了作用 //留着也是不合适的,所以需要在这里删除,当文件上传结束之后,最后生成一个总的字符串,放入到input中,用于传递到后台, //保存到处理过程或者解决方案中,格式为id*name|id*name.... $("#annexStr").remove(); plupload.each(files,function(file) { //file为列队中的单个文件 document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b><a href="javascript:void(0)">删除</a></div>'; }); //调用start开始上传 uploader.start(); return true; }, //当一个文件上传成功之后会调用这个方法, FileUploaded :function(up,file,ret){ /** 参数up为当前上传组件实例,参数file为当前上传到数据库的文件,ret中的response为返回的数据 file内属性有 file{ id:文件编号,包含当前文件名称的一个div的id,很长的字符串,如o_19pemdjmq1ovsoqc1cb11m7ua2ts loaded:已经上传多少字节 name:文件名 percent:上传进度 size:文件大小, status:四中,QUEUED,UPLOADING,FAILED,DONE } */ //将所有在数据库中保存过得文件id和name存储在idName中 idName = idName+ret.response; var currentIdName = ""; //获取当前这个上传文件的idName,并且截取成id*Name格式,如果第一个字符不是"|",则就不需要在进行解决,如果是|则截取 )=="|"){ //去掉第一个|进行保存 currentIdName=ret.response.substring(); }//获取当前文件保存后的id var sqareIndex = currentIdName.indexOf("*"); ,sqareIndex); //动态给每个删除连接添加onclick事件,并且把当前的文件保存后id传过去 $("#"+file.id+" a:first").attr("onclick","deleteAnnex("+currentId+")"); //给每个删除超链接添加上id,该id值为当前文件保存到数据库后的id,即主键 $("#"+file.id+" a:first").attr("id","id"+currentId); }, UploadProgress : function(up, file) { document.getElementById(file.id) .getElementsByTagName(].innerHTML = '<span>' + file.percent + "%</span>"; }, Error : function(up, err) { document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message; }, UploadComplete :function(up,files){ //这个也是为了测试,可以不用 $("#zifuchuan").html(idName); //判断第一个字符是否是| )=="|"){ //去掉第一个|进行保存 idName=idName.substring(); } //此时保存的字符串在后台就不需要在进行截取了 $("#hiddenStr").append("<input id='annexStr' type='text' value="+idName+"></input>"); } } }); //初始化上传组件 uploader.init(); //需要更改隐藏域的值 function deleteAnnex(annexId){ //获取当前超链接的父对象 var $currentHype = $("#id"+annexId).parent(); $.ajax({ type:'post', url:'<c:url value="/deleteAnnex"/>', data:{ annexId:annexId }, success:function(ret){ if(ret=="success"){ $currentHype.remove(); //确保隐藏狂即id为annexStr的隐藏狂内的值是正确的 var idNameStr = $("#annexStr").val(); //用于保存删除后的字符串 var after_delete_idNameStr = ""; )=="|"){ idNameStr=idNameStr.substring(); } //存在| ){ var idNameArr = idNameStr.split("|"); ;i<idNameArr.length;i++){ ){ //包含* ]; if(id!=annexId){ after_delete_idNameStr = after_delete_idNameStr+idNameArr[i]+"|"; } } } } //如果已经没有|,说明只有一个id*name存在了,而此时删除的也正是这个id*name,此时 //after_delete_idNameStr的值为"",删除掉最后一个id*name之后,id为annexStr的隐藏狂的值也为空了 //所以此时只需要下面这行代码就ok //如果从最后一个向前删除,可能最后一个字符是|,需要去掉 )=="|"){ after_delete_idNameStr = after_delete_idNameStr.substring(,after_delete_idNameStr.length-); } $("#annexStr").attr("value",after_delete_idNameStr); //此时idName的值也应该是删除后的值 idName = after_delete_idNameStr; } }, dataType:'json' }) } </script> </body> </html>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>plupload</display-name> <filter> <filter-name>characterEncoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>springServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:action-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>springServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
spring+springmvc配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <!-- springmvc注解,必须配置 --> <context:component-scan base-package="com.h3c.zgc" /> <mvc:annotation-driven /> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"> <value>com.mysql.jdbc.Driver</value> </property> <property name="jdbcUrl"> <value>jdbc:mysql://localhost:3306/itac</value> </property> <property name="user"> <value>root</value> </property> <property name="password"> <value>root</value> </property> <!--连接池中保留的最小连接数。 --> <property name=" /> <!--连接池中保留的最大连接数。Default: --> <property name=" /> <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: --> <property name=" /> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: --> <property name=" /> <property name=" /> <property name=" /> <!--每60秒检查所有连接池中的空闲连接。Default: --> <property name=" /> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: --> <property name=" /> <property name="breakAfterAcquireFailure" value="true" /> <property name="testConnectionOnCheckout" value="false" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.h3c.zgc" /> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.hbm2ddl.auto=update hibernate.connection.autocommit=true hibernate.show_sql=true hibernate.format_sql=true hibernate.cache.use_second_level_cache=true hibernate.cache.use_query_cache=false hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext </value> </property> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="></property> <!-- byte --> <property name="defaultEncoding" value="utf-8" /> </bean> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> <property name="nestedTransactionAllowed" value="true" /> </bean> <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" mode="proxy" /> <!-- 静态资源处理配置 --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
效果:
使用plupload做一个类似qq邮箱附件上传的效果的更多相关文章
- iOS tableViewCell 在cell赋值、网络加载照片位置偏移大小错乱,做一个类似qq列表的tableview 更新3
更新3: 问题 加载慢!(一时间给的处理负载过大,要分散)在下载图片,判断状态后 对每个cell对图片灰置图片处理保存,影响了主线程的操作 :上拉加载时,无法上下滑动tableview 无法点击cel ...
- 日期格式化(类似QQ邮箱中的邮件列表显示日期)
日期格式化(类似QQ邮箱中的邮件列表显示日期) public static string FormatDateDisplay(DateTime _datetime) { var ts = DateTi ...
- winform-实现类似QQ停靠桌面上边缘隐藏的效果
//实现类似QQ停靠桌面上边缘隐藏的效果! private void timer1_Tick(object sender, EventArgs e) { System.Drawing.Point pp ...
- 彻底解决DZ大附件上传问题
个. 注意:很多人遇到修改php.ini后重应WEB服务后仍然不能生效.这种情况应该先确认一下所改的php.ini是不是当前PHP所使用的.您可以在WEB目录下建立一个php文件,内容很简单就一句话& ...
- asp.net结合uploadify实现多附件上传
1.说明 uploadify是一款优秀jQuery插件,主要功能是批量上传文件.大多数同学对多附件上传感到棘手,现将asp.net结合uploadfiy如何实现批量上传附件给大家讲解一下,有什么不对的 ...
- ueditor调用其中的附件上传功能
ueditor实际上是集成了webuploader, 在做内容发布的时候想既有ueditor又有单独的附件上传按钮,这时再加载一个webuploader就显得过于臃肿了,单独利用ueditor的上传功 ...
- 百度在线编辑器UEditor(v1.3.6) .net环境下详细配置教程之更改图片和附件上传路径
本文是接上一篇博客,如果有疑问请先阅读上一篇:百度在线编辑器UEditor(v1.3.6) .net环境下详细配置教程 默认UEditor上传图片的路径是,编辑器包目录里面的net目录下 下面就演示如 ...
- JS实现多附件上传(asp.net)
前几天,用户提出一个需求-多附件上传,另外,每个上传文件要加一个别名,本人创新少,从网上收集了资料,稍微改写,满足了 客户的需求.在应用到程序之前,先做了个小测试,测试通过,小高兴,就记录下了这个小测 ...
- jsp页面附件上传暂存的处理
有没有遇到页面是新建一个新对象,对象里面需要上传附件,但是只有当对象保存时才将附件一同上传到数据库的情况? 这种情况的处理可以参考狐狸的思路: @jsp页面创建一个botton bn,该button的 ...
随机推荐
- 【bootstrapValidator 不验证】使用bootstrapValidator 验证效果不起作用
虽然在页面ready的时候 就绑定了验证表单 ,但是在点击提交按钮之后 依旧没有验证的效果 . 那就在提交按钮的点击事件中 添加一句话: $(document).ready( function () ...
- C# 生成随机数
private static char[] constant = { ', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p ...
- Attribute在.net编程中的应用
Attribute FYI Link: Attribute在.net编程中的应用(一) Attribute在.net编程中的应用(二) Attribute在.net编程中的应用(三) Attribut ...
- 一个linux的样本分析
不久前收到的一个linux样本,之前linux平台下的样本见得并不多,正好做个记录. 样本启动之后,会将自身重命名拷贝到/usr/bin下,并删除自身,如此处就将自身文件amdhzbenfi命名为us ...
- http://www.roncoo.com/course/view/a09d8badbce04bd380f56034f8e68be0
http://www.roncoo.com/course/view/a09d8badbce04bd380f56034f8e68be0
- set+几何 LA 5908 Tracking RFIDs
题目传送门 题意:给一些传感器,范围在r内,再给一些询问点,问这些点能有几个传感器收到,当有墙隔绝时信号减弱,范围变小 分析:set存储传感器,用set的find来查找是否是传感器.因为询问点少,可以 ...
- three.js入门2
新建一个html文件 <!DOCTYPE html> <html> <head> <title></title> <style> ...
- POJ3613 Cow Relays(矩阵快速幂)
题目大概要求从起点到终点恰好经过k条边的最短路. 离散数学告诉我们邻接矩阵的k次幂就能得出恰好经过k条路的信息,比如POJ2778. 这题也一样,矩阵的幂运算定义成min,而min满足结合律,所以可以 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- oracle的内置函数
1.wmsys.wm_concat 行转列函数 select wmsys.wm_concat(destnumber) from mms_send_his_record group by sendn ...