项目地址:
链接:https://pan.baidu.com/s/17FKxu1_09O1q4MLxRgBfKQ
提取码:szua
项目要求:
login.html:
用户名:_____
密码:_____
登录
showAll.html
用户:XXX
文件id 原始名称 新文件名 文件后缀 存储路径 大小 文件类型 是否图片 下载次数 操作
x xxx xxx xxx xxx xx xxx xx xx 下载 在线查看 删除
上传文件:
选择文件________ 点击上传
要求
1.用户登陆展示用户的所有文件文件如果是图片则在页而中显示图片
2.完成文件的下载和在线打开(注意在线打开不计算为下载次数)
3.在一张页面中完成文件的上传功能,上传的目录要根据日期每天创建一个文件夹(文件夹名统一为:“yyyy-mm-dd”),上传完成后要跳转到查询所有页面
引入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sovzn</groupId>
<artifactId>userfiles</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>userfiles</name>
<description>文件的上传和下载</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<!--提供文件上传工具类 FileNameUtils-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件
spring.application.name=files
server.port=8989
server.servlet.context-path=/files
# 关闭thymeleaf的缓存
spring.thymeleaf.cache=false
# 数据库配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/files?characterEncoding=UTF-8&serverTimezone=UTC&useUnicode=true
# mybatis相关
mybatis.mapper-locations=classpath:/com/sovzn/mapper/*.xml
mybatis.type-aliases-package=com.sovzn.entity
#sql日志
logging.level.root=info
logging.level.com.sovzn.dao=debug
开发实体类及数据库
//用户
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)
public class User {
private Integer id;
private String username;
private String password;
}
//文件信息
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)
public class UserFile {
private Integer id;
private String oldFileName;
private String newFileName;
private String ext;
private String path;
private String size;
private String type;
private String isImg;
private Integer downcounts;
private Date uploadTime;
private Integer userid;//用户外键
}
--建库
CREATE DATABASE `files`
USE `files`;
--文件信息表
DROP TABLE IF EXISTS `t_files`;
CREATE TABLE `t_files` (
`id` int(8) NOT NULL AUTO_INCREMENT COMMENT '文件id',
`oldFileName` varchar(200) DEFAULT NULL COMMENT '文件旧名',
`newFileName` varchar(300) DEFAULT NULL COMMENT '文件新名',
`ext` varchar(20) DEFAULT NULL COMMENT '文件后缀',
`path` varchar(300) DEFAULT NULL COMMENT '存储地址',
`size` varchar(200) DEFAULT NULL COMMENT '文件大小',
`type` varchar(120) DEFAULT NULL COMMENT '类型',
`isImg` varchar(8) DEFAULT NULL COMMENT '是否图片',
`downcounts` int(6) DEFAULT NULL COMMENT '下载次数',
`uploadTime` datetime DEFAULT NULL COMMENT '上传时间',
`userid` int(8) DEFAULT NULL COMMENT '用户id',
PRIMARY KEY (`id`),
KEY `user_id` (`userid`),
CONSTRAINT `user_id` FOREIGN KEY (`userid`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
--用户表
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(8) NOT NULL,
`username` varchar(80) DEFAULT NULL,
`password` varchar(80) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `t_user`(`id`,`username`,`password`) values (1,'sovzn','123456'),(2,'syc','123456');
开发Dao
UserDao
@Repository
public interface UserDao {
//用户登录
User login(User user);
}
UserFilesDao
@Repository
public interface UserFilesDao {
//根据当前登录用户的id获取用户的文件列表
List<UserFile> findByUserId(Integer id);
//存贮文件信息
void save(UserFile userFile);
//根据文件id获取文件信息
UserFile findById(String id);
//更新下载次数
void update(UserFile userFile);
//删除文件信息
void delete(String id);
}
开Mapper
UserDaoMapper
<?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.sovzn.dao.UserDao">
<select id="login" resultType="User" parameterType="User">
select * from t_user where username=#{username} and password=#{password}
</select>
</mapper>
UserFilesDaoMapper
<?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.sovzn.dao.UserFilesDao">
<!--根据用户id查询用户文件列表-->
<select id="findByUserId" parameterType="Integer" resultType="UserFile">
select id,oldFileName,newFileName,ext,path,size,type,isImg,downcounts,uploadTime,userid
from t_files
where userid=#{id}
</select>
<!-- 保存文件信息-->
<insert id="save" parameterType="UserFile" >
INSERT INTO t_files (oldFileName, newFileName, ext, path, size, type, isImg, downcounts, uploadTime, userid)
VALUES (#{oldFileName}, #{newFileName},#{ext},
#{path}, #{size}, #{type}, #{isImg}, #{downcounts},
#{uploadTime}, #{userid});
</insert>
<!--根据id获取文件信息-->
<select id="findById" parameterType="String" resultType="UserFile">
select id,oldFileName,newFileName,ext,path,size,type,isImg,downcounts,uploadTime,userid
from t_files
where id=#{id}
</select>
<!--更新下载次数-->
<update id="update" parameterType="UserFile">
update t_files set downcounts=#{downcounts} where id=#{id}
</update>
<!--删除文件信息-->
<delete id="delete" parameterType="String" >
delete from t_files where id=#{id}
</delete>
</mapper>
业务层
UserService
public interface UserService {
User login(User user);
}
UserServiceImpl
@Service
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public User login(User user) {
return userDao.login(user);
}
}
UserFileService
public interface UserFileService {
//查询所有文件
List<UserFile> findByUserId(Integer id);
//保存文件信息
void save(UserFile userFile);
UserFile findById(String id);
//更新下载次数
void update(UserFile userFile);
//删除文件信息
void delete(String id);
}
UserFileServiceImpl
@Service
@Transactional
public class UserFileServiceImpl implements UserFileService {
@Autowired
private UserFilesDao userFilesDao;
@Override
public List<UserFile> findByUserId(Integer id) {
return userFilesDao.findByUserId(id);
}
@Override
public void save(UserFile userFile) {
//是否图片 解决方案:当文件类型Type中以image开头时说明当前的类型一定为图片
String isImg= userFile.getType().startsWith("image")?"是":"否";//判断是否类型以image开头
userFile.setIsImg(isImg);
userFile.setDowncounts(0);
userFile.setUploadTime(new Date());
userFilesDao.save(userFile);
}
@Override
public UserFile findById(String id) {
return userFilesDao.findById(id);
}
@Override
public void update(UserFile userFile) {
userFilesDao.update(userFile);
}
@Override
public void delete(String id) {
userFilesDao.delete(id);
}
}
控制器
indexController
@Controller
public class indexController {
@GetMapping("index")
public String tologin(){
return "login";//跳转到登录页
}
}
UserController
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
//登录
@PostMapping("login")
public String login(User user, HttpSession session){
System.out.println("进入登录");
User u= userService.login(user);
if (u!=null){
session.setAttribute("user",u);
return "redirect:/file/findAll";
}
else {
return "redirect:/index";
}
}
}
FileController
@Controller
@RequestMapping("file")
public class FileController {
@Autowired
private UserFileService userFileService;
//展示所有文件-----------------------------------------------------
@GetMapping("findAll")
public String findAll(HttpSession session, Model model){
System.out.println("查询所有文件");
//在session中获取用户
User user=(User)session.getAttribute("user");
System.out.println(user);
List<UserFile> listfiles=userFileService.findByUserId(user.getId());
//将得到的文件列表存入model作用域
model.addAttribute("files",listfiles);
return "showAll";
}
//上传文件,并保存文件的信息到数据库中
@PostMapping("upload")
//注意:下面的aaa一定要与上传文件表单中的name属性值一致,否则接收不到
public String uploadFile(MultipartFile aaa,HttpSession session) throws IOException {
User user = (User)session.getAttribute("user");
// 获取文件信息--------------------------------------------
//获取文件的原始名称
String oldFileName=aaa.getOriginalFilename();
//获取文件的后缀
String ext= "."+FilenameUtils.getExtension(aaa.getOriginalFilename());
//生成新文件名
String newFileName=new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+ UUID.randomUUID().toString().replace("-","+")+ext;
// 获取文件大小
Long size= aaa.getSize();
//文件类型
String type=aaa.getContentType();
//处理文件上传---------------------------------------------
//获取文件存贮路径(绝对路径) 注意classpath后的:号 一般springboot项目里classpath目录指的是resources文件夹
String realpath= ResourceUtils.getURL("classpath:").getPath()+"/static/files";
//根据日期生成文件存储子目录
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());//得到当前日期
String dateDirPath=realpath+"/"+format;
File dateDir=new File(dateDirPath);//根据生成的dateDirPath创建文件 dateDir
//判断dateDir是否存在,不存在就创建
//注意:mkdirs()和mkdir()区别 mkdirs()可以创建多级目录
if(!dateDir.exists()) {
dateDir.mkdirs();
}
//文件上传
aaa.transferTo(new File(dateDir,newFileName));
System.out.println("开始上传文件");
//将文件信息放入数据库中
UserFile userFile = new UserFile();
userFile.setOldFileName(oldFileName)
.setNewFileName(newFileName)
.setExt(ext)
.setSize(String.valueOf(size))
.setType(type)
.setPath("/files/"+format)
.setUserid(user.getId());
userFileService.save(userFile);
return "redirect:/file/findAll";
}
//文件下载-----------------------------------------------------------
@GetMapping("download")
public void download(String id, HttpServletResponse response) throws IOException {
System.out.println("文件下载----");
//获取文件信息
UserFile userFile= userFileService.findById(id);
//更新下载次数
userFile.setDowncounts(userFile.getDowncounts()+1);
userFileService.update(userFile);
//根据文件信息中的文件名和文件的存储路径获取文件输入流
//获取下载文件的路径(绝对路径)
String realpath=ResourceUtils.getURL("classpath:").getPath()+"/static"+userFile.getPath();
//获取文件输入流
FileInputStream is = new FileInputStream(new File(realpath, userFile.getNewFileName()));
//附件下载 (文件旧名)
response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(userFile.getOldFileName(),"UTF-8"));
//获取响应输出流
ServletOutputStream os= response.getOutputStream();
//文件拷贝
IOUtils.copy(is,os);
//关流
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
//在线打开-----------------------------------------------------------
@GetMapping("openinline")
public void openinline(String id, HttpServletResponse response) throws IOException {
System.out.println("在线打开----");
//获取文件信息
UserFile userFile= userFileService.findById(id);
//根据文件信息中的文件名和文件的存储路径获取文件输入流
//获取在线打开文件的路径(绝对路径)
String realpath=ResourceUtils.getURL("classpath:").getPath()+"/static"+userFile.getPath();
//获取文件输入流
FileInputStream is = new FileInputStream(new File(realpath, userFile.getNewFileName()));
//附件下载 (文件旧名)
//注意:在线打开和文件下载差不多,只需将下列的attachment改为inline
response.setHeader("content-disposition","inline;fileName="+ URLEncoder.encode(userFile.getOldFileName(),"UTF-8"));
//获取响应输出流
ServletOutputStream os= response.getOutputStream();
//文件拷贝
IOUtils.copy(is,os);
//关流
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
@GetMapping("delete")
//删除文件信息----------------------------------------------
public String delete(String id) throws FileNotFoundException {
System.out.println("删除文件");
System.out.println(id);
//根据id查询文件信息
UserFile userFile= userFileService.findById(id);
//删除文件---
String realpath= ResourceUtils.getURL("classpath:").getPath()+"static"+userFile.getPath();
File file=new File(realpath,userFile.getNewFileName());
if(file.exists()){
file.delete();
}
//删除数据库中的信息---
userFileService.delete(id);
return "redirect:/file/findAll";
}
}
页面
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body style="text-align: center">
<!--thymeleaf的语法@{}可以解析到项目根目录名(该项目名为server.servlet.context-path=/files)
,比如th:action="@{/user/login}" 在执行时,会解析为action="/files/user/login"-->
<form th:action="@{/user/login}" method="post" style="margin-top: 200px">
<h1>欢迎访问用户文件管理系统</h1>
Username:<input type="text" name="username" ><br/>
Password:<input type="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
文件列表 showAll.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户文件列表页面</title>
<script th:src="@{/js/jquery-3.2.1.slim.min.js}" ></script>
</head>
<body>
<h1 th:text="${'欢迎:'+session.user.username}"></h1>
<h3>文件列表</h3>
<table border="1px">
<tr>
<th>ID</th>
<th>文件原始名称</th>
<th>文件新名称</th>
<th>文件后缀</th>
<th>存储路径</th>
<th>文件大小</th>
<th>类型</th>
<th>是否是图片</th>
<th>下载次数</th>
<th>上传时间</th>
<th>操作</th>
</tr>
<tr th:each="file,fileStat:${files}" >
<td><span th:text="${file.id}"/></td>
<td><span th:text="${file.oldFileName}"/></td>
<td><span th:text="${file.newFileName}"/></td>
<td><span th:text="${file.ext}"/></td>
<td><span th:text="${file.path}"/></td>
<td><span th:text="${file.size}"/></td>
<td><span th:text="${file.type}"/></td>
<td>
<img th:if="${file.isImg}=='是'" th:src="${#servletContext.contextPath}+${file.path}+'/'+${file.newFileName}" alt="图片">
<span th:if="${file.isImg}=='否'" th:text="${file.isImg}"/>
</td>
<td><span th:text="${file.downcounts}"/></td>
<td><span th:text="${file.uploadTime}"/></td>
<td>
<a th:href="@{/file/download(id=${file.id})}">下载</a>
<a th:href="@{/file/openinline(id=${file.id})}">在线打开</a>
<a th:href="@{/file/delete(id=${file.id})}">删除</a>
</td>
</tr>
</table>
<hr>
<h3>上传文件</h3>
<!--enctype="multipart/form-data"
不对字符编码。
在使用包含文件上传控件的表单时,必须使用该值。-->
<form th:action="@{/file/upload}" method="post" enctype="multipart/form-data">
<input type="file" name="aaa">
<input type="submit" value="上传文件">
</form>
</body>
</html>
给个饭钱?
- Post link: http://sovzn.github.io/2021/01/21/SpringBoot-Mybatis%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E5%92%8C%E4%B8%8B%E8%BD%BD/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues