在java领域中SpringBoot是一个非常好用的框架,可以快速地构建web项目,这里记录一下使用SpringBoot来实现文件的上传、下载和在线预览功能。
1.创建数据库和数据库表
本文主要用到用户和用户所属的文件,所以这里就只需要设计用户表和文件表即可。
用户表t_user
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(80) DEFAULT NULL,
`password` varchar(80) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
insert into t_user(username, password) values("pikacho", "123456");
文件表t_files
CREATE TABLE `t_files` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`file_name` varchar(200) DEFAULT NULL,
`ext` varchar(20) DEFAULT NULL,
`path` varchar(300) DEFAULT NULL,
`size` bigint(64) DEFAULT NULL,
`type` varchar(120) DEFAULT NULL,
`download_counts` int(6) DEFAULT NULL,
`upload_time` datetime DEFAULT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `t_files_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2.创建SpringBoot项目
这里不用多说,使用IDEA创建SpringBoot项目,删除多余没用的文件,让项目结构保持简洁。
简单地创建一个控制器,然后启动项目,测试该SpringBoot项目是否构建成功。
@Controller
public class HelloController {
@RequestMapping("hello")
@ResponseBody
public String hello(){
return "hello SpringBoot";
}
}
访问项目:http://localhost:8080/hello,出现如下画面说明项目能够成功运行;先保证项目能成功运行,然后再考虑开发功能。
3.添加该项目需要的依赖以及配置基本环境
pom.xml依赖
<dependencies>
<!-- thymeleaf模板引擎的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- SpringBoot的web项目依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok依赖,作用是创建实体类时不用自己手动添加构造器,setter等方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<!-- 文件上传依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- druid数据库连接池依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yml主配置文件
spring:
application:
name: fileStorage
thymeleaf:
cache: false
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/fileservice?serverTimezone=Asia/Shanghai&userUnicode=true&characterEncoding=utf-8
username: root
password: root
server:
port: 8080
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: com.pikacho.entity
添加完依赖以及将主配置文件配置完成,完成本项目功能需要的基本环境就已经全部搭建完成了,启动项目测试项目是否可以正常运行;出现下面的画面说明项目基本环境搭建成功。
4.用户登录、注销及注册功能
4.1.完成登录功能
即使一个非常简单的demo项目,也是少不了前端页面。对于一个后端开发者来说,要自己去写前端页面布局和样式是一件挺痛苦也困难的事(是真的不会写啊!)。所以这里使用layui框架来快速构建前端页面。当然,这只是简单的使用一下该框架,想要熟练使用。还需继续深入学习才行。
1.引入layui
将layui需要的文件添加到static文件夹下
2.创建登录页面
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>login</title>
<link rel="stylesheet" th:href="@{/css/layui.css}">
</head>
<body>
<div class="layui-container">
<div class="layui-row" style="margin-top: 80px;">
<div class="layui-col-lg4 layui-col-lg-offset4">
<h1 style="margin:20px; text-align: center"> 请 登 录 </h1>
<form class="layui-form" th:action="@{/user/login}" , method="post">
<div class="layui-form-item">
<p style="color: red; text-align: center" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
</div>
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="username" required autocomplete="false">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密 码</label>
<div class="layui-input-block">
<input class="layui-input" type="password" name="password" required autocomplete="false">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">立即登录</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<div style="float:right">
<a th:href="@{/user/toRegister}">去注册</a>
</div>
</div>
</div>
</div>
<script th:src="@{/layui.js}"></script>
<script>
//一般直接写在一个js文件中
layui.use(['layer', 'form'], function(){
var layer = layui.layer
,form = layui.form;
});
</script>
</body>
</html>
UserController.java
/**
* 前往登录页面
* @return
*/
@RequestMapping("toLogin")
public String toLogin(){
return "login";
}
这样,之后我们就可以轻松地创建前端页面了,并且不用自己去设计样式和布局等问题。还是要提一下,像这样简单使用一下这种程度就够了,但是要熟练使用的话,就要更加深入学习才行。
3.完成登录功能
- 创建User实体类--User.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Integer id;
private String username;
private String password;
}
- 创建UserDao及其mapper映射文件--UserDao.java & UserDaoMapper.xml
@Mapper
@Repository
public interface UserDao {
/**
* 用户登录功能
* @return
*/
public User login(User user);
}
<?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.pikacho.dao.UserDao">
<!-- public User login(User user)-->
<select id="login" parameterType="User" resultType="User">
select id, username, password
from t_user
where username = #{username} and password = #{password};
</select>
- 创建UserService类及其实现类--UserService.java & UserServiceImpl.java
public interface UserService {
public User login(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
public UserDao userDao;
@Override
public User login(User user){
return userDao.login(user);
}
}
- 利用Shiro框架实现登录认证功能
Shiro框架可以快速实现登录认证等安全权限功能,这里也是简单使用一下,想要深入理解使用还需查阅其官方文档。
UserRealm.java
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){
return null;
}
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;
User user = new User();
user.setUsername(usernamePasswordToken.getUsername());
user.setPassword(String.valueOf(usernamePasswordToken.getPassword()));
// 从数据库查询出来
User userDB = userService.login(user);
if(userDB == null){
return null;
}
return new SimpleAuthenticationInfo(userDB, user.getPassword(), "");
}
}
ShiroConfig.java
@Configuration
public class ShiroConfig {
// 第一步:创建UserRealm对象
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
// 第二步:创建默认安全管理器DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(
@Qualifier("userRealm") UserRealm userRealm ){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
// 第三步:创建ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(
@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(securityManager);
/*
* anon: 无需认证就能访问
authc: 必须认证后才能访问
user: 必须拥有 记住我 功能才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/
// 拦截/file/* ,该路径只有登录的情况下才能查看
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/file/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
// 设置没有访问权限时,跳转页面
bean.setLoginUrl("/login");
return bean;
}
}
- 在UserController类中添加登录方法
@PostMapping("login")
public String login(User user, Model model){
Subject subject = SecurityUtils.getSubject();
// 封装用户信息
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
try{
subject.login(token);
Session session = subject.getSession();
session.setAttribute("user", (User)subject.getPrincipal());
// 前往文件列表页面
return "list";
}catch (UnknownAccountException e){
model.addAttribute("msg", "用户名或密码错误");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg", "用户名或密码错误");
return "login";
}
}
- 最后在SpringbootFileuploadApplication类上添加包扫描注解,不然mybatis无法将接口和xml配置文件绑定起来
@SpringBootApplication
@MapperScan(basePackages = "com.pikacho.dao")
public class SpringbootFileuploadApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootFileuploadApplication.class, args);
}
}
登录功能代码已经开发完毕了,现在测试一下功能是否正常。
访问项目:http://localhost:8080/user/toLogin,之前创建用户表时,就已经创建了一个用户。用户名:pikacho 密码:123456。
4.2.完成注册功能
1.创建注册页面
register.html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>register</title>
<link rel="stylesheet" th:href="@{/css/layui.css}">
</head>
<body>
<div class="layui-container">
<div class="layui-row" style="margin-top: 80px;">
<div class="layui-col-lg4 layui-col-lg-offset4">
<h1 style="margin:20px; text-align: center"> 请 注 册 </h1>
<div class="layui-form-item">
<p style="color: red; text-align: center" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
</div>
<form class="layui-form" th:action="@{/user/register}" method="post">
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="username" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密 码</label>
<div class="layui-input-block">
<input class="layui-input" type="password" name="password" required autocomplete="false">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formDemo">立即注册</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<div style="float:right">
<a th:href="@{/user/toLogin}">去登录</a>
</div>
</div>
</div>
</div>
<script th:src="@{/layui.js}"></script>
<script>
//一般直接写在一个js文件中
layui.use(['layer', 'form'], function(){
var layer = layui.layer
,form = layui.form;
});
</script>
</body>
</html>
2.完成注册功能
- 在UserDao类中添加register(),编写mapper映射文件
/**
*
* @param user
*/
public void register(User user);
<!-- 注册-->
<insert id="register" parameterType="User">
insert into t_user (username, password)
values(#{username}, #{password});
</insert>
- 在UserService类及实现类中添加注册方法
/**
*
* @param user
*/
public void register(User user);
/**
*
* @param user
*/
@Override
public void register(User user){
userDao.register(user);
}
- 在UserController类中添加注册逻辑
测试注册功能, 访问项目:http://localhost:8080/user/toRegister ;添加用户pikacho2 :123456
4.3.创建list页面
前面只是简单的创建一个list页面验证登录功能,现在补全list页面。
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>FileList</title>
<link rel="stylesheet" th:href="@{/css/layui.css}">
</head>
<body>
<div class="layui-fluid">
<nav class="layui-nav">
<div class="layui-nav-item">
<p class="layui-nav-title" style="font-size: larger">
欢迎:<span th:if="${session.user!=null}" th:text="${session.user.username}"/>
</p>
</div>
<div class="layui-nav-item" style="float: right;">
<button class="layui-btn">
<a th:href="@{/user/logout}" style="font-size: larger; padding: 0px; color: white">login out</a>
</button>
</div>
<div class="layui-nav-item" style="float: right; padding-right: 20px">
<button type="button" class="layui-btn" id="fileUpload">
上传文件
</button>
</div>
</nav>
<!-- 文件列表-->
<table id="fileList" lay-filter="fileTable"></table>
<script type="text/html" id="optBar">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="download">下载</a>
<a class="layui-btn layui-btn-xs" lay-event="preview">预览</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">删除</a>
</script>
</div>
<script th:src="@{/layui.js}" charset="utf-8"></script>
</body>
</html>
4.4.完成注销功能
- 在UserController类中添加注销方法
/**
* 注册功能
* @return
*/
@GetMapping("logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
// 这里需要注意:redirect:user/toLogin 实际的请求路径http://localhost:8080/user/user/toLogin
// 所以需要使用redirect:toLogin
return "redirect:toLogin";
}
5.文件的展示、上传、删除、下载功能
5.1.文件的展示
- 创建文件实例类--UserFile.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Accessors(chain = true)
public class UserFile {
private Integer id;
private String fileName;
private String ext;
private String path;
private long size;
private String type;
private Integer downloadCounts;
private Date uploadTime;
private Integer userId;
}
- 创建UserFileDao及其mapper映射文件
@Mapper
@Repository
public interface UserFileDao {
/**
* 根据用户id获得用户文件列表
* @param id
* @param begin
* @param offset
* @return
*/
public List<UserFile> queryByUserId(Integer id, Integer begin, int offset);
/**
* 根据用户id获得该用户文件总数
* @param id
* @return
*/
public int queryFileCount(Integer id);
}
<?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.pikacho.dao.UserFileDao">
<resultMap id="UserFileMap" type="UserFile">
<!-- 只需要映射列名和属性名不一致的-->
<id column="id" property="id"></id>
<result column="file_name" property="fileName"></result>
<result column="download_counts" property="downloadCounts"></result>
<result column="upload_time" property="uploadTime"></result>
<result column="user_id" property="userId"></result>
</resultMap>
<!-- 根据用户id查询文件列表-->
<select id="queryByUserId" parameterType="Integer" resultMap="UserFileMap">
select * from t_files
where user_id = #{id}
order by id
limit #{begin}, #{offset};
</select>
<!-- 根据用户id查询文件数量-->
<select id="queryFileCount" parameterType="Integer" resultType="Integer">
select count(*) from t_files
where user_id = #{id};
</select>
</mapper>
- 创建UserFileService类及其实现类
public interface UserFileService {
/**
* 根据用户id获得文件列表
* @param id
* @param page
* @param limit
* @return
*/
public List<UserFile> queryByUserId(Integer id, Integer page, Integer limit);
/**
* 根据用户id获得文件数
* @param id
* @return
*/
public int queryFileCounts(Integer id);
}
@Service
public class UserFileServiceImpl implements UserFileService {
@Autowired
private UserFileDao userFileDao;
/**
* 根据用户id获得文件列表
* @param id
* @param page
* @param limit
* @return
*/
@Override
public List<UserFile> queryByUserId(Integer id, Integer page, Integer limit){
// page表示第几页,limit表示每页显示多少行数据
int begin = (page-1)*limit; // 该计算方法获得开始的位置
int offset = limit;
return userFileDao.queryByUserId(id, begin, limit);
}
/**
* 根据用户id获得文件数
* @param id
* @return
*/
@Override
public int queryFileCounts(Integer id){
return userFileDao.queryFileCounts(id);
}
}
- 创建UserFileController类
@Controller
@RequestMapping("file")
public class UserFileController {
@Autowired
private UserFileService userFileService;
/**
* 返回文件列表
* @param session
* @param request
* @return
*/
@PostMapping("all")
@ResponseBody
public Map<String, Object> queryAllFile(HttpSession session, HttpServletRequest request){
int page = Integer.parseInt(request.getParameter("page"));
int limit = Integer.parseInt(request.getParameter("limit"));
User user = (User) session.getAttribute("user");
List<UserFile> files = userFileService.queryByUserId(user.getId(), page, limit);
Map<String, Object> res = new HashMap<>();
res.put("code", 0);
res.put("count", userFileService.queryFileCounts(user.getId()));
res.put("data", files);
return res;
}
}
- 接着在list.html中添加渲染表格的脚本
// 渲染表格
table.render({
elem: '#fileList',
height: 600,
minWidth: 80,
url: '/file/all', // 这一定要是/file/all,之前我是file/all不停的报错,无法访问成功
parseData: function (res) {
return {
"code": res.code,
"msg": "",
"count": res.count,
"data": res.data
};
},
method: 'post',
limit: 10,
page: true,
cols: [[
{field:'id', title:'ID', sort:true, fixed:'left'},
{field:'fileName', title:'文件名'},
{field:'ext', title:'文件后缀'},
{field:'path', title:"存储路径"},
{field:'size', title:'大小'},
{field:'type', title:"类型"},
{field:'downloadCounts', title:'下载次数'},
{field:'uploadTime', title:'上传时间'},
{tilte:'操作',align:'center', toolbar:'optBar', width:200, fixed:'right'}
]]
});
5.2.文件上传
- 在UserFileDao类中添加上传文件方法及mapper映射文件
/**
* 上传文件
* @param userFile
*/
public void save(UserFile userFile);
<!-- 上传文件-->
<insert id="save" parameterType="UserFile" useGeneratedKeys="true" keyProperty="id">
insert into t_files(file_name, ext, path, size, type, download_counts, upload_time, user_id)
values(#{fileName}, #{ext}, #{path}, #{size}, #{type}, #{downloadCounts}, #{uploadTime}, #{userId});
</insert>
- 在UserFileService类及UserFileServiceImpl类中添加方法
/**
* 上传文件
* @param userFile
*/
public void save(UserFile userFile);
/**
* 上传文件
* @param userFile
*/
@Override
public void save(UserFile userFile){
userFile.setDownloadCounts(0).setUploadTime(new Date());
userFileDao.save(userFile);
}
- 在UserFileController类中添加上传文件接口
@GetMapping("index")
public String fileIndex(){
return "list";
}
/**
* 上传文件
* @param file
* @param session
* @return
*/
@PostMapping("upload")
@ResponseBody
public Map<String, String> uploadFile(@RequestParam("file")MultipartFile file, HttpSession session){
Map<String, String> res = new HashMap<>();
try{
User user = (User) session.getAttribute("user");
String fileName = file.getOriginalFilename();
String extension = FilenameUtils.getExtension(fileName);
long size = file.getSize();
String type = file.getContentType();
// 根据日期生成目录
String localContainer = "/fileContainer";
String uploadPath = ResourceUtils.getURL("classpath").getPath()+localContainer;
String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File dateDirPath = new File(uploadPath+File.separator+dateFormat);
if(!dateDirPath.exists()){
dateDirPath.mkdirs();
}
file.transferTo(new File(dateDirPath, fileName));
// 将文件信息存入数据库
UserFile userFile = new UserFile();
userFile.setFileName(fileName)
.setExt('.'+extension)
.setPath(Paths.get(localContainer, dateFormat, fileName).toString())
.setSize(size)
.setType(type)
.setUserId(user.getId());
userFileService.save(userFile);
res.put("code", "0");
res.put("msg", "上传成功");
res.put("url", "/file/index");
}catch(IOException e){
res.put("code", "-1");
res.put("msg", "上传失败");
res.put("url", "/file/index");
}
return res;
}
这里文件存储在我的本地磁盘上,文件表中存储的是文件在我磁盘存储的存储路径。
5.3.文件下载
开发流程与上面基本一致。
// UserFiledao
/**
* 下载文件
* @param id
* @return
*/
public UserFile queryByUserFileId(Integer id);
/**
* 更新文件下载次数
* @param userFile
*/
public void update(UserFile userFile);
// UserFileService
/**
* 下载文件
* @param id
* @return
*/
public UserFile queryByUserFileId(Integer id);
/**
* 跟新文件下载次数
* @param userFile
*/
public void update(UserFile userFile);
// UserFileServiceImpl
/**
* 下载文件
* @param id
* @return
*/
@Override
public UserFile queryByUserFileId(Integer id) {
return userFileDao.queryByUserFileId(id);
}
/**
* 跟新文件下载次数
* @param userFile
*/
@Override
public void update(UserFile userFile) {
userFileDao.update(userFile);
}
<!-- 下载文件-->
<select id="queryByUserFileId" parameterType="Integer" resultMap="UserFileMap">
select * from t_files where id = #{id};
</select>
<!-- 更新文件下载次数-->
<update id="update" parameterType="UserFile">
update t_files set download_counts = #{downloadCounts} where id = #{id};
</update>
/**
* 下载文件
* @param id
* @param response
*/
@GetMapping("download/{id}")
public void download(@PathVariable("id") Integer id, HttpServletResponse response){
String openStyle = "attachment";
try{
getFile(openStyle, id, response);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 更新文件下载次数
* @param openStyle
* @param id
* @param response
* @throws Exception
*/
public void getFile(String openStyle, Integer id, HttpServletResponse response) throws Exception {
UserFile userFile = userFileService.queryByUserFileId(id);
String realPath = ResourceUtils.getURL("classpath").getPath()+userFile.getPath();
FileInputStream is = new FileInputStream(new File(realPath));
// 附件下载
response.setHeader("content-disposition", openStyle+";filename=" + URLEncoder.encode(userFile.getFileName(), "UTF-8"));
// 获取响应response输出流
ServletOutputStream os = response.getOutputStream();
// 文件拷贝
IOUtils.copy(is, os);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
if(openStyle.equals("attachment")){
userFile.setDownloadCounts(userFile.getDownloadCounts()+1);
userFileService.update(userFile);
}
}
list.html
//监听工具条
table.on('tool(fileTable)', function (obj) {
var data = obj.data;
if (obj.event === 'download') {
window.open("/file/download/" + data.id);
obj.update({
"downloadCounts": data.downloadCounts + 1
});
} else if (obj.event === 'delete') {
layer.confirm('真的删除文件吗?', function (index) {
$.ajax({
url: "/file/delete/" + data.id,
type: "Get",
success: function (res) {
layer.msg(res.msg);
obj.del();
},
error: function (res) {
$.message.alert('msg', res.msg);
}
});
layer.close(index);
});
} else if (obj.event === 'preview') {
layer.open({
type: 2,
skin: 'layui-layer-demo', //样式类名
title: '文件预览',
closeBtn: 1, //显示关闭按钮
anim: 2,
area: ['893px', '600px'],
shadeClose: true, //开启遮罩关闭
content: '/file/preview/' + data.id
});
}
});
5.4.文件删除
文件删除开发流程也是同上。
6.完成文件预览功能
- 添加预览方法
/**
* 文件预览
* @param id
* @param response
* @throws IOException
*/
@GetMapping("preview/{id}")
public void preview(@PathVariable("id") Integer id, HttpServletResponse response) throws Exception {
String openStyle = "inline";
getFile(openStyle,id,response);
}
到此,这个小项目就基本完成。
demo源码地址https://github.com/picacho-pkq/SpringBoot-demo
demo下载地址https://download.youkuaiyun.com/download/pikcacho_pkq/75146243