SpringMVC实现文件上传和下载功能

一、文件上传功能

目录结构

设立流程

  • 设计数据表,将项目id和上传文件路径的对应关系存到数据库中。
    结构包括:主键、项目id(外键)、文件目录、重命名后的文件名、原文件名。
  • 逆向工程生成dao、po、mapper,xml
  • 在project的edit.jsp中增加一段html的文件上传标记。
  • 编写service和controller实现上传功能。
  • 编辑页面显示文件,根据projectid找到对应的文件对象的,将原文件名显示在页面上。

1.数据库表结构

create table tb_files(
	fid int primary key not null auto_increment,
	projectid int,
	path varchar(255),
	filename varchar(255),
	origname varchar(255)
)

2.dao包

通过逆向工程生成 TbFilesMapper接口

public interface TbFilesMapper {
    int countByExample(TbFilesExample example);

    int deleteByExample(TbFilesExample example);

    int deleteByPrimaryKey(Integer fid);

    int insert(TbFiles record);

    int insertSelective(TbFiles record);

    List<TbFiles> selectByExample(TbFilesExample example);

    TbFiles selectByPrimaryKey(Integer fid);

    int updateByExampleSelective(@Param("record") TbFiles record, @Param("example") TbFilesExample example);

    int updateByExample(@Param("record") TbFiles record, @Param("example") TbFilesExample example);

    int updateByPrimaryKeySelective(TbFiles record);

    int updateByPrimaryKey(TbFiles record);
}

3.po包

TbFiles.java

public class TbFiles {
    private Integer fid;

    private Integer projectid;

    private String path;

    private String filename;

    private String origname;

    public Integer getFid() {
        return fid;
    }

    public void setFid(Integer fid) {
        this.fid = fid;
    }

    public Integer getProjectid() {
        return projectid;
    }

    public void setProjectid(Integer projectid) {
        this.projectid = projectid;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path == null ? null : path.trim();
    }

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename == null ? null : filename.trim();
    }

    public String getOrigname() {
        return origname;
    }

    public void setOrigname(String origname) {
        this.origname = origname == null ? null : origname.trim();
    }
}

4.service包

FileService接口

public interface FileService {
    public List<TbFiles> query(int projectid);
}

FileServiceImpl.java

@Service//将该类注册到IOC容器中生成对应的Bean
public class FileServiceImpl implements FileService{
    @Autowired
    private TbFilesMapper filesMapper;
    @Override
    public List<TbFiles> query(int projectid) {
        TbFilesExample example=new TbFilesExample();
        TbFilesExample.Criteria criteria=example.createCriteria();
        criteria.andProjectidEqualTo(projectid);
        return filesMapper.selectByExample(example);
    }
}

ProjectService接口

public interface ProjectService {
    public void update(MultipartFile[] files,TbProject project,String realPath);
    public TbProject queryById(int id);
}

ProjectServiceImpl.java

@Service
public class ProjectServiceImpl implements ProjectService{
    @Autowired
    private TbProjectMapper projectMapper;
    @Autowired
    private TbFilesMapper filesMapper;

    @Override
    public void update(MultipartFile[] files,TbProject project,String realPath) {
        int count=0;
        for(MultipartFile f:files){
            //重命名
            //截取后缀名
            String hzm="";
            int index=f.getOriginalFilename().lastIndexOf(".");
            if(index!=-1){
                hzm=f.getOriginalFilename().substring(index);
            }
            //生成一个不重复的名字
            String name=String.valueOf(new Date().getTime())+(++count);//用当前时间的毫秒值作为名字,为了使名字不重复,count为计数器
            //上传文件存储在部署路径的upload文件夹中,文件名是重命名的文件名
            File dirFile=new File(realPath,"upload");//将部署的路径传进来
            if(!dirFile.exists())//如果不存在就建立文件夹
                dirFile.mkdir();
            File saveFile=new File(dirFile,name+hzm);//dirFile为父文件夹,要存的文件名name+hzm
            try {
                f.transferTo(saveFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //向数据库存储关系
            TbFiles tbFiles=new TbFiles();
            tbFiles.setProjectid(project.getProjectid());
            tbFiles.setFilename(name+hzm);
            tbFiles.setOrigname(f.getOriginalFilename());//源文件名
            tbFiles.setPath(dirFile.getPath());//存储的路径
            filesMapper.insert(tbFiles);
        }
        projectMapper.updateByPrimaryKeySelective(project);
    }
}

5.controller包

ProjectController.java

@Controller
@RequestMapping("/project")
public class ProjectController {
    @Autowired
    private ProjectService projectService;//注入
    @Autowired
    private FileService fileService;

    @RequestMapping("/edit")
    public String edit(int id,Map map){
        //查询项目经理的集合,查客户的集合,传到add.jsp页面
        TbProject project=projectService.queryById(id);
        List<TbFiles> files=fileService.query(id);
        List<TbEmp> managers=empService.query(3);
        List<TbCompany> companies=companyService.query();
        map.put("managers",managers);
        map.put("companies",companies);
        map.put("project",project);
        map.put("files",files);
        return "/project/edit";

    }
    @RequestMapping("/update")
    public String update(MultipartFile[] file, TbProject project, HttpServletRequest request){
        projectService.update(file,project,request.getServletContext().getRealPath(""));//得到部署的路径传进去
        return "redirect:/project/query";//重定向跳转
    }
   
}

6.resources包

通过逆向工程生成的 TbFilesMapper.xml

<?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.hyxy.dao.TbFilesMapper" >
  <resultMap id="BaseResultMap" type="com.hyxy.po.TbFiles" >
    <id column="fid" property="fid" jdbcType="INTEGER" />
    <result column="projectid" property="projectid" jdbcType="INTEGER" />
    <result column="path" property="path" jdbcType="VARCHAR" />
    <result column="filename" property="filename" jdbcType="VARCHAR" />
    <result column="origname" property="origname" jdbcType="VARCHAR" />
  </resultMap>
 
  <update id="updateByPrimaryKeySelective" parameterType="com.hyxy.po.TbFiles" >
    update tb_files
    <set >
      <if test="projectid != null" >
        projectid = #{projectid,jdbcType=INTEGER},
      </if>
      <if test="path != null" >
        path = #{path,jdbcType=VARCHAR},
      </if>
      <if test="filename != null" >
        filename = #{filename,jdbcType=VARCHAR},
      </if>
      <if test="origname != null" >
        origname = #{origname,jdbcType=VARCHAR},
      </if>
    </set>
    where fid = #{fid,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.hyxy.po.TbFiles" >
    update tb_files
    set projectid = #{projectid,jdbcType=INTEGER},
      path = #{path,jdbcType=VARCHAR},
      filename = #{filename,jdbcType=VARCHAR},
      origname = #{origname,jdbcType=VARCHAR}
    where fid = #{fid,jdbcType=INTEGER}
  </update>
</mapper>

7.webapp

edit.jsp

<%--
Created by IntelliJ IDEA.
User: 86159
Date: 2022/7/5
Time: 8:54
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>项目管理系统</title>
    <link rel="stylesheet" rev="stylesheet"
          href="${pageContext.request.contextPath}/css/style.css" type="text/css" media="all" />
    <style type="text/css">
        <!--
        .atten {font-size:12px;font-weight:normal;color:#F00;}
        -->
    </style>
    <script src="${pageContext.request.contextPath}/js/jquery-1.9.1.min.js"></script>
    <script>
        $(function(){
            $("#saveBtn").click(function(){
                saveForm.submit();
            });
            $("#addFile").click(function(){
                $("#filetd").append("<input type='file' name='file'/><br>")
            });

        });
    </script>
</head>
<body class="ContentBody">
<form action="${pageContext.request.contextPath}/project/update" method="post" enctype="multipart/form-data"
      name="saveForm" >
    <input type="hidden" name="projectid" value="${project.projectid}">
    <div class="MainDiv">
        <table width="99%" border="0" cellpadding="0" cellspacing="0" class="CContent">
            <tr>
                <th class="tablestyle_title" >项目编辑</th>
            </tr>
            <tr>
                <td class="CPanel">
                    <table border="0" cellpadding="0" cellspacing="0"
                           style="width:100%">
                        <TR>
                            <TD width="100%">
                                <fieldset style="height:100%;">
                                    <legend>项目信息</legend>
                                    <table border="0" cellpadding="2" cellspacing="1"
                                           style="width:100%">
                                        <tr>
                                            <td nowrap align="right" width="15%">项目名称:</td>
                                            <td width="35%"><input name='projectname'
                                                                   value="${project.projectname}" type="text" class="text" style="width:154px" />
                                                <span class="red">*</span></td>
                                            <td nowrap align="right" width="18%">所属单位:</td>
                                            <td width="35%">
                                                    <select name="companyid">
                                                        <option value="">请选择</option>
                                                        <c:forEach items="${companies}" var="c">
                                                            <option value="${c.companyid}"
                                                                    <c:if test="${project.companyid==c.companyid}">selected</c:if> >${c.companyname}
                                                            </option>
                                                        </c:forEach>
                                                    </select>
                                                <span class="red">*</span></td>
                                        </tr>
                                        <tr>
                                            <td nowrap align="right" width="15%">项目金额:</td>
                                            <td width="35%"><input name='amount'
                                                                   value="${project.amount}" type="text" class="text" style="width:154px"/>
                                            </td>
                                            <td nowrap align="right" width="18%">开发人数:</td>
                                            <td width="35%"><input name='prosum'
                                                                   value="${project.prosum}" type="text" class="text" style="width:154px"/>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td nowrap align="right" width="15%">项目经理:</td>
                                            <td width="35%">
                                                <select name="empid">
                                                    <option value="">请选择</option>
                                                    <c:forEach items="${managers}"
                                                               var="e">
                                                        <option value="${e.empid}" <c:if
                                                                test="${project.empid==e.empid}">selected</c:if> >${e.empname}</option>
                                                    </c:forEach>
                                                </select>
                                            </td>
                                            <td nowrap align="right" width="18%">完成状态:</td>
                                            <td width="35%">
                                                <select name="state">
                                                    <option selected="selected">请选择</option>
                                                    <option value="0" <c:if test="${project.state==0}">selected</c:if> >需求</option>
                                                    <option value="1" <c:if test="${project.state==1}">selected</c:if> >开发</option>
                                                    <option value="2" <c:if test="${project.state==2}">selected</c:if> >测试</option>
                                                    <option value="3" <c:if test="${project.state==3}">selected</c:if> >完成</option>
                                                </select>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td nowrap align="right" width="15%">预算总成本:</td>
                                            <td width="35%"><input name='budget'
                                                                   value="${project.budget}" type="text" class="text" style="width:154px"  />
                                            </td>
                                            <td nowrap="nowrap" align="right">开始日期:</td>
                                            <td><input name='realbegindate'
                                                       value="<fmt:formatDate value='${project.realbegindate}' pattern="yyyy-MM-dd"/>" type="text" class="text" style="width:154px"/> </td>
                                        </tr>
                                        <tr>
                                            <td nowrap="nowrap" align="right">完成日期:</td>
                                            <td><input name='realenddate'
                                                       value="<fmt:formatDate value='${project.realenddate}' pattern="yyyy-MM-dd"/>" type="text" class="text" style="width:154px" />
                                            </td>
                                            <td align="right" >优先级:</td>
                                            <td ><select name="priority" >
                                                <option selected="selected">请选择</option>
                                                <option value="0" <c:if test="${project.priority==0}">selected</c:if> >普通</option>
                                                <option value="1" <c:if test="${project.priority==1}">selected</c:if> >急</option>
                                                <option value="2" <c:if test="${project.priority==2}">selected</c:if> >特急</option>
                                            </select></td>
                                        </tr>
                                        <tr>
                                            <td width="15%" nowrap align="right">备注:
                                            </td>
                                            <td colspan="3"><textarea name="descript"
                                                                      cols="100" rows="10">${project.descript}</textarea></td>
                                        </tr>

                                        <tr>
                                            <td  colspan="4" nowrap align="left"><a id="addFile" href="javascript:void(0);">添加文件</a></td>
                                        </tr>
                                        <tr>
                                            <td  colspan="4" nowrap align="left">
                                                <c:forEach items="${files}" var="f">
                                                    ${f.origname}&nbsp;&nbsp;<a href="${pageContext.request.contextPath}/project/download?id=${f.fid}">下载</a>&nbsp;&nbsp;<a href="javascript:void(0);">删除</a><br>
                                                </c:forEach>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td  colspan="4" id="filetd" nowrap align="left"></td>
                                        </tr>

                                    </table>
                                    <br/>
                                </fieldset> </TD>
                        </TR>
                    </TABLE>
                </td>
            </tr>
            <TR>
                <TD colspan="2" align="center" height="50px">
                    <input type="button" name="Submit" value="保存" id="saveBtn"
                           class="button" />
                    <input type="button" name="Submit2" value="返回" class="button"
                           onclick="window.history.go(-1);"/></TD>
            </TR>
        </TABLE>
        </td>
        </tr>
        </table>
    </div>
</form>
</body>
</html>

8.spring的xml配置文件

applicationContext.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:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xmlns:tx="http://www.springframework.org/schema/tx" 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://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/project?useUnicode=true&amp;characterEncoding=utf8" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath*:com/hyxy/mapper/*.xml"></property>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=mysql
                            reasonable=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>

    </bean>
    <mybatis-spring:scan base-package="com.hyxy.dao"/>
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <tx:annotation-driven transaction-manager="txManager" />
    <context:component-scan base-package="com.hyxy.service"></context:component-scan>
</beans>

9.导入的依赖

    <!-- 文件上传包 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>

10.显示效果

浏览器访问 项目查询页面–点击编辑按钮–点击添加文件超链接–选择上传文件–点击保存按钮
http://localhost/8080/project/project/query
添加文件
在这里插入图片描述
再次访问编辑页面可查看上传的文件
在这里插入图片描述

数据库存储的projectid和上传文件的关系表
在这里插入图片描述

二、文件下载功能

目录结构

1.service包

FileService接口

public interface FileService {
    public TbFiles queryById(int fid);
}

FileServiceImpl.java

@Service
public class FileServiceImpl implements FileService{
    @Autowired
    private TbFilesMapper filesMapper;

    @Override
    public TbFiles queryById(int fid) {
        return filesMapper.selectByPrimaryKey(fid);
    }
}

2.controller包

ProjectController.java

@Controller
@RequestMapping("/project")
public class ProjectController {
    @Autowired
    private ProjectService projectService;//注入
    @Autowired
    private EmpService empService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private FileService fileService;

    @RequestMapping("/update")
    public String update(MultipartFile[] file, TbProject project, HttpServletRequest request){
        projectService.update(file,project,request.getServletContext().getRealPath(""));
        return "redirect:/project/query";
    }
    @RequestMapping("/download")
    public ResponseEntity<byte[]> download(int id){
        TbFiles files=fileService.queryById(id);
        File downloadFile=new File(files.getPath(),files.getFilename());//要下载的文件
        HttpHeaders headers = new HttpHeaders();
        //通知浏览器以attachment(下载方式)打开图片
        headers.setContentDispositionFormData("attachment", files.getOrigname());//原文件名
        //application/octet-stream : 二进制流数据(最常见的文件下载)。
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(downloadFile),
                    headers, HttpStatus.CREATED);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3.功能测试

点击下载功能的超链接即可下载到本地
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aigo-2021

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值