学习过程 | SSM框架实现基本的文件上传下载功能

(只用看image相关的文件,paper和user不用)

1.项目结构

学习过程 | SSM框架实现基本的文件上传下载功能

   学习过程 | SSM框架实现基本的文件上传下载功能学习过程 | SSM框架实现基本的文件上传下载功能

 

项目结构内容解释(按照构建顺序)

1.pojo:存放项目涉及得到实体类,实体的属性和setter,getter方法

package com.pojo;

public class Image {
    private int id;


    private String content;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

}

2.dao:存放对数据库操作的接口

package com.dao;

import com.pojo.Image;

import java.util.List;

public interface ImageDao {
    int add(String content);

    int deleteById(int id);

    List<Image> queryAllImage();

    String queryImageById(int id);
}

3.service:存放对pojo实体类的操作接口,与dao接口相对应

package com.service;

import com.pojo.Image;

import java.util.List;

public interface ImageService {
    List<Image> queryAllImage();

    int add(Image image);

    int deleteById(int id);

    String queryImageById(int id);

}

4.service下的impl包:存放service下接口的实现类,每个方法返回对dao中接口方法的调用,注意注解不要丢了

package com.service.impl;

import com.dao.ImageDao;
import com.pojo.Image;
import com.service.ImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class ImageServiceImpl implements ImageService {
    @Autowired
    private ImageDao imageDao;
    @Override
    public int add(Image image) {
        return imageDao.add(image.getContent());
    }

    @Override
    public int deleteById(int id) {
        return imageDao.deleteById(id);
    }

    @Override
    public List<Image> queryAllImage() {
        return imageDao.queryAllImage();
    }

    public String queryImageById(int id) {
        return imageDao.queryImageById(id);
    }
}

5.mapper:对dao中方法的实现,对数据库进行增删改除操作,具体细节可以查看MyBatis教程

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.ImageDao">
    <resultMap type="Image" id="imageResultMap" >
        <!--property是类中的属性,column是数据库中的列-->
        <id property="id" column="image_id"/>
        <result property="content" column="image_content"/>
    </resultMap>
    <insert id="add" parameterType="Image">
        INSERT INTO image(image_content)
        VALUES (#{content})

    </insert>

    <delete id="deleteById" parameterType="int">
        delete from image where image_id = #{id}
    </delete>

    <select id="queryAllImage" resultMap="imageResultMap">
        select image_id,image_content from image
    </select>

    <select id="queryImageById" resultType="String" parameterType="int">
        select image_content from image where image_id=#{id};
    </select>
</mapper>

6.配置文件

spring-dao.xml

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置整合mybatis过程 -->
    <!-- 1.配置数据库相关参数properties的属性:${url} -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 2.数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置连接池属性 -->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 扫描pojo包 使用别名 -->
        <property name="typeAliasesPackage" value="com.pojo"/>
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="com.dao"/>
    </bean>
</beans>

spring-mvc.xml

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <!-- 配置SpringMVC -->
    <!-- 1.开启SpringMVC注解模式 -->
    <!-- 简化配置:
        (1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
        (2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持
    -->
    <mvc:annotation-driven />

    <!-- 2.静态资源默认servlet配置
        (1)加入对静态资源的处理:js,gif,png
        (2)允许使用"/"做整体映射
     -->
    <mvc:default-servlet-handler/>

    <!-- 3.配置jsp 显示ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="209715200" />
        <property name="defaultEncoding" value="UTF-8" />
        <property name="resolveLazily" value="true" />
    </bean>

    <!-- 4.扫描web相关的bean -->
    <context:component-scan base-package="com.controller" />
</beans>

spring-service.xml

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="com.service" />

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/papersystem?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=password

log4j.properties

log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

mybatis-congif.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置全局属性 -->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />

        <!-- 使用列别名替换列名 默认:true -->
        <setting name="useColumnLabel" value="true" />

        <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>
</configuration>

6.jsp页面

index.jsp

<%--JSP指令page:定义页面的依赖属性--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%--隐含对象pageContext:PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问--%>
<%
    pageContext.setAttribute("path", request.getContextPath());
%>

<!DOCTYPE HTML>
<html>
<head>
    <title>首页</title>
    <style type="text/css">
        a {
            text-decoration: none;
            color: black;
            font-size: 18px;
        }

        h3 {
            width: 180px;
            height: 38px;
            margin: 100px auto;
            text-align: center;
            line-height: 38px;
            background: deepskyblue;
            border-radius: 4px;
        }
    </style>
</head>
<body>
<%--bootstrap网格的基本结构--%>
<div class="container">
    <%--clearfix清除浮动--%>
    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    基于SSM框架的管理系统:简单实现增、删、改、查。
                </h1>
            </div>
        </div>
    </div>
</div>
<br><br>
<h3>
    <a href="${path }/image/allImage">点击进入管理页面</a>
</h3>
</body>
</html>

allImage.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/2/22
  Time: 15:56
  To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    pageContext.setAttribute("path", request.getContextPath());

%>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>allImage</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row clearfix">
        <div class="col-md-12 column" >
            <div class="page_header">
                <h1>图片列表</h1>
            </div>
        </div>
    </div>

    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table">
                <thead>
                <tr>
                    <td>序号</td>
                    <td>内容</td>
                    <td>图片显示</td>
                    <td>删除</td>
                    <td>下载</td>
                </tr>
                </thead>
                <tbody>
                <c:forEach var="image" items="${requestScope.get('list1')}" varStatus="status1">
                    <tr>
                        <td>${image.id}</td>
                        <td>${image.content}</td>
                        <td>
                            <img id="images" alt="" width="100" height="100" src="/myImage1/${image.content }">
                        </td>
                        <td><a href="${path}/image/delete/${image.id}">删除</a> </td>
                        <td><a href="${path}/image/down/${image.id }">下载</a> </td>
                    </tr>

                </c:forEach>


                </tbody>
            </table>
        </div>
    </div>
<%-- 存项目中的图片   <c:forEach var="b" items="${list1}">
        <img src="http://localhost:8080/first/${b.content}">
    </c:forEach>--%>

    <div class="row clearfix">
        <div class="col-md-12 column">
            <a href="${path}/image/addImage"><button>增加</button></a>
        </div>
    </div>
</div>
</body>
</html>

addImage.jsp

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2018/4/7
  Time: 16:45
  To change this template use File | Settings | File Templates.
--%>
<%--JSP指令taglib:引入标签库的定义,可以是自定义标签,下面是引入核心标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
    out.print(path);
    /*path = ""*/
    /*basepath=http://localhost:8080/*/
%>
<html>
<head>
    <title>新增论文</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    基于SSM框架的管理系统:简单实现增、删、改、查。
                </h1>
            </div>
        </div>
    </div>

    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>新增论文</small>
                </h1>
            </div>
        </div>
    </div>
    <form action="" name="userForm">
        <%--这里的name是属性名--%>
        论文名称:<input type="text" name="paperName"><br><br><br>
        论文数量:<input type="text" name="paperNum"><br><br><br>
        论文详情:<input type="text" name="paperDetail"><br><br><br>
        <input type="button" value="添加" onclick="addPaper()">
    </form>

    <script type="text/javascript">
        function addPaper() {
            var form = document.forms[0];
            form.action = "<%=basePath %>paper/addPaper";
            form.method = "post";
            form.submit();
        }
    </script>
</div>

7.controller

imageController

package com.controller;

import com.pojo.Image;
import com.service.ImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/image")
public class ImageController {
    @Autowired
    private ImageService imageService;

    @RequestMapping("/allImage")
    public String queryAllImage(Model model) {
        List<Image> list1 = imageService.queryAllImage();
        System.out.println(list1.size());
        for (Image i:list1
             ) {
            System.out.println(i.getContent()+","+i.getId());
        }
        model.addAttribute("list1", list1);
        return "allImage";
    }

    @RequestMapping("/addImage")
    public String addImage() {
        return "addImage";
    }

    @RequestMapping(value="/doAddImage",method = RequestMethod.POST)
    public String doAddImage(@RequestParam(value = "file") MultipartFile[] file, Image image,  HttpServletRequest request) throws IOException {
        /**
         * 图片上传到项目
         */
        /*
        //上传后的地址,注意("/upload")是表示文件上传后的目标文件夹
        String realPath = request.getSession().getServletContext().getRealPath("/upload");
        System.out.println("=========打印文件上传的路径"+realPath);
        for (int i = 0; i < file.length; i++) {
            //获取文件名
            String filename = file[i].getOriginalFilename();
            //获取文件后缀名
            String extensionname = filename.substring(filename.lastIndexOf(".") + 1);
            //给上传的文件起别名,有很多种方式
            String newFilename=String.valueOf(System.currentTimeMillis())+"."+extensionname;
            //创建File对象,传入目标路径参数,和新的文件别名
            File dir=new File(realPath,newFilename);
            if (!dir.exists()){//如果dir代表的文件不存在,则创建它,
                dir.mkdirs();//
            }
            //如果存在则直接执行下面操作
            file[i].transferTo(dir);//将上传的实体文件复制到指定目录upload下
            image.setContent(newFilename);//将文件名赋值给实体类,然后一并存到数据库
            imageService.add(image);//调用后台方法,将对象存进数据库
        }

*/
        /**
         * 图片上传到本地
         */

        //图片上传成功后,将图片的地址写到数据库
        String filePath = "d:\\myImage1";
        for (int i = 0; i < file.length; i++) {
            //获取文件名
            String filename = file[i].getOriginalFilename();
            //获取文件后缀名
            String extensionname = filename.substring(filename.lastIndexOf(".") + 1);
            //给上传的文件起别名,有很多种方式
            String newFileName=String.valueOf(System.currentTimeMillis())+"."+extensionname;

            //封装上传文件位置的全路径,就是硬盘路径+文件名
            File targetFile = new File(filePath,newFileName);
            System.out.println("!!!!!!!========="+targetFile);
            if (!targetFile.exists()){//如果dir代表的文件不存在,则创建它,
                targetFile.mkdirs();
            }
            //把本地文件上传到已经封装好的文件位置的全路径就是上面的targetFile
            file[i].transferTo(targetFile);
            image.setContent(newFileName);//文件名保存到实体类对应属性上
            //保存商品
            imageService.add(image);
        }


        return "redirect:/image/allImage";
    }

    /*文件下载*/
    @RequestMapping("/down/{id}")
    public void download(@PathVariable("id") int id, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        //根据选择文件的编号,查找到相应的文件名字
        String beginname = imageService.queryImageById(id);
        System.out.println("@@@@@@@@@@@@@@@@@@@0" + beginname);
        //生成文件的存储位置
        String fileName = "d:\\myImage1"+"/"+ beginname;
        System.out.println("!!!!!!!!!!!!!!!!!" + fileName);
        //封装为完整的文件路径
        File file = new File(fileName);
        //如果文件存在的话
        if (file.exists()) {
            //获取输入流
            InputStream bis = new BufferedInputStream(new FileInputStream(file));
            //假如以中文名下载的话
            String filename = beginname;
            //转码,免得文件名中文乱码
            filename = URLEncoder.encode(filename, "UTF-8");
            //设置文件下载头
            response.addHeader("Content-Disposition", "attachment;filename=" + filename);
            //1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
            response.setContentType("multipart/form-data");
            /*getOutputStream获取子程序的输出流*/
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            int len = 0;
            while ((len = bis.read()) != -1) {
                out.write(len);
                /*将缓冲区中的数据写入到输出流中*/
                out.flush();
            }
            out.close();
        } else {
            //下载的文件不存在
            request.setAttribute("errorResult", "文件不存在下载失败!");
            RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/01.jsp");
            dispatcher.forward(request, response);
        }

    }

    /*根据文件序号删除指定的文件*/
    @RequestMapping("/delete/{id}")
    public String deleteImageById(@PathVariable("id") int id) {
        imageService.deleteById(id);
        return "redirect:/image/allImage";
    }
}