springMVC+spring+hibernate注解上传文件到数据库,下载,多文件上传

时间:2021-02-08 18:57:37

数据库

CREATE TABLE `annex` (
  `id` bigint() NOT NULL AUTO_INCREMENT,
  `realName` varchar() DEFAULT NULL,
  `fileContent` mediumblob,
  `handId` bigint() DEFAULT NULL,
  `customerId` bigint() DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_id` (`handId`),
  CONSTRAINT `fk_id` FOREIGN KEY (`handId`) REFERENCES `handprocess` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `handprocess` (
  `id` bigint() NOT NULL DEFAULT ',
  `handTime` bigint() DEFAULT NULL,
  `handName` varchar() DEFAULT NULL,
  `reason` varchar() DEFAULT NULL,
  `annexStr` varchar() DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

处理过程(handprocess)和附件表(annex)一对多关系,一条处理过程可以有多个附件

除了springmvc+hibernate+spring的jar,还需要

commons-fileupload-1.3.1.jar

commons-io-2.0.1.jar

数据库保存上传文件内容使用mediumblob类型

mysql保存数据库二进制文件使用blob类型,其大小如下

TinyBlob 最大
Blob 最大 65K
MediumBlob 最大 16M
LongBlob 最大 4G

springmvc中需添加配置文件

<bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="></property>  <!-- byte -->
        <property name="defaultEncoding" value="utf-8" />
    </bean>

其中maxUploadSizes的大小是上传文件大小,单位:字节

实体:

package com.h3c.zgc.upload;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
 * 附件     和处理过程多对一
 * @author GoodLuck
 *
 */
@Entity
@Table(name="annex",catalog="itac")
public class Annex {
    @Id
    @Column(name="id")
    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;

    //getter and setter ...

}
package com.h3c.zgc.upload;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name="handprocess",catalog="itac")
public class HandProcess {

    @Id
    @Column(name="id")
    private Long id;
    @Column(name="handTime")
    private Long handTime;
    @Column(name="handName")
    private String handName;
    @Column(name="reason")
    private String reason;
    @Column(name="annexStr")
    private String annexStr;
    @Transient
    private String handTimeStr;

    //getter and setter ...

}

dao层

package com.h3c.zgc.upload;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

@Repository
public class UploadDownDao extends HibernateDaoSupport{
    @Resource
    public void set(SessionFactory sessionFactory){
        this.setSessionFactory(sessionFactory);
    }

    public Session getSession(){
        return this.getSessionFactory().openSession();
    }
    /**
     * 获取附件id最大值
     */
    public Long getMaxIdOfAnnex(){
        List l = this.getHibernateTemplate().find("select max(id) from Annex");
        System.out.println(l);
        &&l.)!=null){
            );
        }
        return 0L;
    }
    /**
     * 获取处理过程id最大值
     * @return
     */
    public Long getMaxIdOfHandProcess(){
        List l = this.getHibernateTemplate().find("select max(id) from HandProcess");
        System.out.println(l);
        &&l.)!=null){
            );
        }
        return 0L;
    }
    /**
     * 保存附件
     * @param annex
     * @return
     */
    public Serializable saveAnnex(Annex annex){
        return this.getHibernateTemplate().save(annex);
    }
    /**
     * 保存处理过程
     * @param hp
     * @return
     */
    public Serializable saveHandProcess(HandProcess hp){
        return this.getHibernateTemplate().save(hp);
    }
    /**
     * 获取处理过程列表,左连接查询
     * @return
     */
    public List getHandProcessList(){//有没有可能没有附件,附件annex,处理过程handprocess
        SQLQuery query = this.getSession().createSQLQuery("select h.id handprocessId,h.annexStr annexStr,a.id annexId,a.realName realName,h.handTime handTime,h.handName handName,h.reason reason from handprocess h left join annex a on a.handId=h.id");
        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List list = query.list();
        return list;
    }
    /**
     * 根据id获取附件信息
     * @param annexId
     * @return
     */
    public Annex getAnnexById(Long annexId){
        return this.getHibernateTemplate().get(Annex.class, annexId);
    }
    /**
     * 修改处理过程
     * @param hp
     */
    public void updateHandProcess(HandProcess hp){
        this.getHibernateTemplate().update(hp);
    }
}

service层

package com.h3c.zgc.upload;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.springframework.stereotype.Service;

@Service
public class UploadDownService {

    @Resource
    private UploadDownDao uploadDownDao;

    public Long getMaxIdOfAnnex(){
        return this.uploadDownDao.getMaxIdOfAnnex();
    }
    public Long getMaxIdOfHandProcess(){
        return this.uploadDownDao.getMaxIdOfHandProcess();
    }
    @Transactional
    public Serializable saveAnnex(Annex annex){
        return this.uploadDownDao.saveAnnex(annex);
    }
    @Transactional
    public Serializable saveHandProcess(HandProcess hp){
        return this.uploadDownDao.saveHandProcess(hp);
    }
    public Annex getAnnexById(Long annexId){
        return this.uploadDownDao.getAnnexById(annexId);
    }
    public List<Map<String,Object>> getHandProcessList(){
        return this.uploadDownDao.getHandProcessList();
    }
    @Transactional
    public void updateHandProcess(HandProcess hp){
        this.uploadDownDao.updateHandProcess(hp);
    }
}

controller层

package com.h3c.zgc.upload;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
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.multipart.MultipartFile;

@Controller
public class UploadDownFileController {
    @Resource
    private UploadDownService uploadDownService;
    //单文件上传到数据库,MultipartFile中封装了上传文件的信息
    @RequestMapping("upload")
    public String upload(HandProcess hp, HttpServletRequest request,
            @RequestParam("uploadFile1") MultipartFile uploadFile1)
            throws IOException, ParseException {

        InputStream is = uploadFile1.getInputStream();
        byte[] buffer = this.inputStrean2ByteArr(is);
        /**
         * 保存处理过程信息
         */
        // get max id then ++1
        Long hpMaxId = this.uploadDownService.getMaxIdOfHandProcess();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        hp.setHandTime(df.parse(hp.getHandTimeStr()).getTime());
        hp.setId(hpMaxId + );
        //保存处理过程
        Serializable hpId = this.uploadDownService.saveHandProcess(hp);
        /**
         * 保存附件
         */
        Annex annex = new Annex();
        annex.setCustomerId(1L);
        annex.setHandId((Long) hpId);
        annex.setRealName(uploadFile1.getOriginalFilename());
        annex.setFileContent(buffer);
        //查找附件id最大值
        annex.setId();
        Serializable aid = this.uploadDownService.saveAnnex(annex);
        /**
         * 获取处理过程列表
         */
        List<Map<String, Object>> as = this.uploadDownService
                .getHandProcessList();
        for (Map<String, Object> map : as) {
            map.put("handTime", df.format(map.get("handTime")));
        }
        request.setAttribute("as", as);
        return "annex/annexList";
    }
    /**
     * 多文件上传
     * @param hp   处理过程
     * @param request
     * @param uploadFile1   上传文件
     * @return
     * @throws IOException
     * @throws ParseException
     */
    @RequestMapping("uploadOneMore")
    public String uploadOneMore(HandProcess hp, HttpServletRequest request,
            @RequestParam("uploadFile1") MultipartFile[] uploadFile1)
            throws IOException, ParseException {
        /**
         * 保存处理过程信息
         */
        // get max id then ++1
        Long hpMaxId = this.uploadDownService.getMaxIdOfHandProcess();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        hp.setHandTime(df.parse(hp.getHandTimeStr()).getTime());
        hp.setId(hpMaxId + );
        //
        Serializable hpId = this.uploadDownService.saveHandProcess(hp);
        //保存改工单下的所有附件
        ; i < uploadFile1.length; i++) {
            InputStream is = uploadFile1[i].getInputStream();
            byte[] buffer = this.inputStrean2ByteArr(is);

            /**
             * 保存附件
             */
            Annex annex = new Annex();
            annex.setCustomerId(1L);
            annex.setHandId((Long) hpId);
            annex.setRealName(uploadFile1[i].getOriginalFilename());
            annex.setFileContent(buffer);
            annex.setId();
            Serializable annexId = this.uploadDownService.saveAnnex(annex);

        }
        //多文件上传,一个处理过程下面要有多个附件,在页面中显示的时候,一个处理过程后面要显示多个附件
        //更新表handprocess
        this.uploadDownService.updateHandProcess(hp);

        List<Map<String, Object>> as = this.uploadDownService
                .getHandProcessList();
        request.setAttribute("as", as);
        return "annex/annexList";
    }

    /**
     * 文件下载
     * @param response
     * @param annexId
     * @throws IOException
     */
    @RequestMapping("download")
    public void download(HttpServletResponse response, Long annexId)
            throws IOException {
        Annex a = this.uploadDownService.getAnnexById(annexId);
        byte[] b = a.getFileContent();
        response.setContentType("application/octet-stream;charset=UTF-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition",
                "attachment;filename=" + new String(a.getRealName().getBytes("gbk"),"iso-8859-1"));  //防止文件乱码

        BufferedOutputStream bos = new BufferedOutputStream(
                response.getOutputStream());
        bos.write(b);
        bos.close();
    }
    /**
     * inputstream转成byte数组
     * @param inStream
     * @return
     * @throws IOException
     */
    public byte[] inputStrean2ByteArr(InputStream inStream) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        ];
        ;
        , )) > ) {
            swapStream.write(buff, , rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }

}

main.jsp

<%@ 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>
</head>
<body>
<a href="${pageContext.request.contextPath }/getAllStudent">查找所有用户</a>
<a href="${pageContext.request.contextPath }/savePerson">单独保存Person</a>
<a href="${pageContext.request.contextPath }/savePersonHouse">保存Person和House</a>
<br/>
<form action="${pageContext.request.contextPath }/getArr" >
    <input type="text" name="workSheetId"/><br/>
    <input type="submit" value="search"/>
</form>
<br/><br/><br/>
<form action="<c:url value="/upload"/>" method="post" enctype="multipart/form-data">
    处理时间:<input type="text" name="handTimeStr"/><br>
    处理人:<input type="text" name="handName"/><br/>
    原因:<input type="text" name="reason"/><br/>
    选择文件:<input type="file" name="uploadFile1"/><br/>
    <input type="submit" value="submit"/>
</form>
<br/>
upload one more
<form action="<c:url value="/uploadOneMore"/>" method="post" enctype="multipart/form-data">
    处理时间:<input type="text" name="handTimeStr"/><br>
    处理人:<input type="text" name="handName"/><br/>
    原因:<input type="text" name="reason"/><br/>
    选择文件:<input type="file" name="uploadFile1"/><br/>
    选择文件:<input type="file" name="uploadFile1"/><br/>
    选择文件:<input type="file" name="uploadFile1"/><br/>
    <input type="submit" value="submit"/>
</form>
</body>
</html>

annexList.jsp  显示处理过程已经处理过程下附件

<%@ 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>
</head>
<body>
    <table>
        <c:forEach items="${as }" var="ah" varStatus="status">
            <tr>
                <td>${ah['handprocessId'] }</td>
                <td>${ah['handName'] }</td>
                <td>${ah['reason'] }</td>
                <td id="id${status.index }">${ah['handTime'] }</td>

                <td>
                    ${ah['annex']['realName'] }
                    <a href="<c:url value="/download?annexId=${ah['annexId'] }"/>">${ah['realName'] }</a>
                </td>
            </tr>
        </c:forEach>

    </table>
</body>
<script type="text/javascript">

</script>
</html>