公司项目中使用的框架是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邮箱附件上传的效果的更多相关文章

  1. iOS tableViewCell 在cell赋值、网络加载照片位置偏移大小错乱,做一个类似qq列表的tableview 更新3

    更新3: 问题 加载慢!(一时间给的处理负载过大,要分散)在下载图片,判断状态后 对每个cell对图片灰置图片处理保存,影响了主线程的操作 :上拉加载时,无法上下滑动tableview 无法点击cel ...

  2. 日期格式化(类似QQ邮箱中的邮件列表显示日期)

    日期格式化(类似QQ邮箱中的邮件列表显示日期) public static string FormatDateDisplay(DateTime _datetime) { var ts = DateTi ...

  3. winform-实现类似QQ停靠桌面上边缘隐藏的效果

    //实现类似QQ停靠桌面上边缘隐藏的效果! private void timer1_Tick(object sender, EventArgs e) { System.Drawing.Point pp ...

  4. 彻底解决DZ大附件上传问题

    个. 注意:很多人遇到修改php.ini后重应WEB服务后仍然不能生效.这种情况应该先确认一下所改的php.ini是不是当前PHP所使用的.您可以在WEB目录下建立一个php文件,内容很简单就一句话& ...

  5. asp.net结合uploadify实现多附件上传

    1.说明 uploadify是一款优秀jQuery插件,主要功能是批量上传文件.大多数同学对多附件上传感到棘手,现将asp.net结合uploadfiy如何实现批量上传附件给大家讲解一下,有什么不对的 ...

  6. ueditor调用其中的附件上传功能

    ueditor实际上是集成了webuploader, 在做内容发布的时候想既有ueditor又有单独的附件上传按钮,这时再加载一个webuploader就显得过于臃肿了,单独利用ueditor的上传功 ...

  7. 百度在线编辑器UEditor(v1.3.6) .net环境下详细配置教程之更改图片和附件上传路径

    本文是接上一篇博客,如果有疑问请先阅读上一篇:百度在线编辑器UEditor(v1.3.6) .net环境下详细配置教程 默认UEditor上传图片的路径是,编辑器包目录里面的net目录下 下面就演示如 ...

  8. JS实现多附件上传(asp.net)

    前几天,用户提出一个需求-多附件上传,另外,每个上传文件要加一个别名,本人创新少,从网上收集了资料,稍微改写,满足了 客户的需求.在应用到程序之前,先做了个小测试,测试通过,小高兴,就记录下了这个小测 ...

  9. jsp页面附件上传暂存的处理

    有没有遇到页面是新建一个新对象,对象里面需要上传附件,但是只有当对象保存时才将附件一同上传到数据库的情况? 这种情况的处理可以参考狐狸的思路: @jsp页面创建一个botton bn,该button的 ...

随机推荐

  1. 【bootstrapValidator 不验证】使用bootstrapValidator 验证效果不起作用

    虽然在页面ready的时候 就绑定了验证表单 ,但是在点击提交按钮之后 依旧没有验证的效果 . 那就在提交按钮的点击事件中 添加一句话: $(document).ready( function () ...

  2. C# 生成随机数

    private static char[] constant = { ', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p ...

  3. Attribute在.net编程中的应用

    Attribute FYI Link: Attribute在.net编程中的应用(一) Attribute在.net编程中的应用(二) Attribute在.net编程中的应用(三) Attribut ...

  4. 一个linux的样本分析

    不久前收到的一个linux样本,之前linux平台下的样本见得并不多,正好做个记录. 样本启动之后,会将自身重命名拷贝到/usr/bin下,并删除自身,如此处就将自身文件amdhzbenfi命名为us ...

  5. http://www.roncoo.com/course/view/a09d8badbce04bd380f56034f8e68be0

    http://www.roncoo.com/course/view/a09d8badbce04bd380f56034f8e68be0

  6. set+几何 LA 5908 Tracking RFIDs

    题目传送门 题意:给一些传感器,范围在r内,再给一些询问点,问这些点能有几个传感器收到,当有墙隔绝时信号减弱,范围变小 分析:set存储传感器,用set的find来查找是否是传感器.因为询问点少,可以 ...

  7. three.js入门2

    新建一个html文件 <!DOCTYPE html> <html> <head> <title></title> <style> ...

  8. POJ3613 Cow Relays(矩阵快速幂)

    题目大概要求从起点到终点恰好经过k条边的最短路. 离散数学告诉我们邻接矩阵的k次幂就能得出恰好经过k条路的信息,比如POJ2778. 这题也一样,矩阵的幂运算定义成min,而min满足结合律,所以可以 ...

  9. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  10. oracle的内置函数

    1.wmsys.wm_concat   行转列函数 select wmsys.wm_concat(destnumber) from mms_send_his_record group by sendn ...