文件上传下载实战
文件上传下载实战
登录模块
-
springboot JWT 拦截器
请求头字段问题Authorization
-
axios
传递字段 axios
传递字段: key: Authorization value: token
-
api
位置问题 -
修改前
api
位置问题 -
修改后
api
位置
-
-
使用
axios
拦截器对请求添加 token
所需字段 使用 axios
拦截器对请求添加 token
所需字段 -
devServer
配置不生效问题 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54import axios from 'axios'
let baseURL = '/'
if (process.env.NODE_ENV === 'production') {
// 后端接口地址
baseURL = 'http://localhost:8081/'
}
export function request(config) {
const instance = axios.create({
baseURL,
timeout: 5000,
})
// 未登录时 token 是空的
const token = window.localStorage.getItem('token')
// 请求拦截器
instance.interceptors.request.use(
config => {
// 每次发送请求之前判断是否存在token,如果存在,则统一在 http 请求的 header 都加上 token,不用每次请求都手动添加了
if (token) {
// 设置统一的 request header Authorization
config.headers.Authorization = token
}
return config
},
err => {
return Promise.reject(err)
}
)
// http response 服务器响应拦截器,这里拦截401 错误,并重新跳入登页重新获取 token
instance.interceptors.response.use(
response => {
return response
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 这里写清除token 的代码
router.replace({
path: 'login',
query: { redirect: router.currentRoute.fullPath }, // 登录成功后跳入浏览的当前页面
})
}
}
return Promise.reject(error.response.data)
}
)
// 发送真正的网络请求(Promise)
return instance(config)
} -
Login.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154<template>
<div class="login">
<el-form
:model="ruleForm"
status-icon
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="用户名" prop="userName">
<el-input
v-model="ruleForm.userName"
type="text"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="pass">
<el-input
type="password"
v-model="ruleForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
type="password"
v-model="ruleForm.checkPass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">
登录
</el-button>
<el-button type="danger" @click="resetForm('ruleForm')">
重置
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
// 后期容易维护
import { loginApi, testApi } from '@/network/user/login'
export default {
data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass')
}
callback()
}
}
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.ruleForm.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
ruleForm: {
userName: 'coder-itl',
password: 'root',
checkPass: 'root',
},
rules: {
pass: [
{
required: true,
validator: validatePass,
trigger: 'blur',
},
],
checkPass: [
{
required: true,
validator: validatePass2,
trigger: 'blur',
},
],
userName: [
{
required: true,
message: '请输入用户名',
trigger: 'blur',
},
{
min: 5,
max: 15,
message: '长度在 5 到 15 个字符',
trigger: 'blur',
},
],
},
}
},
methods: {
// 登录提交
submitForm(formName) {
this.$refs[formName].validate(async valid => {
if (valid) {
let _this = this
let param = {
userName: _this.ruleForm.userName,
password: _this.ruleForm.password,
}
// 发起 axios 请求
const { data: res } = await loginApi(param)
// 存储用户信息
window.localStorage.setItem(
'token',
// JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串
res.token
)
// 登录成功后发送
testApi().then(res => {
console.log(res)
})
_this.$router.push('/home')
} else {
_this.$message.error('登录失败')
return false
}
})
},
// 重置
resetForm(formName) {
this.$refs[formName].resetFields()
},
},
}
</script>
<style lang="less" scoped>
.login {
width: 80%;
margin: 100px auto;
padding: 30px;
box-shadow: 0 0 10px 10px rgba(212, 212, 212, 0.3);
}
</style> -
后端生成
token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Map<String, Object> login(User user) {
log.info("user: {}", user.toString());
// 数据库用户
User userDB = userService.login(user);
Map<String, Object> map = new HashMap<>();
// 生成 tocken
Map<String, String> payload = new HashMap<>();
// token 携带的数据
payload.put("username", userDB.getUserName());
payload.put("userId", String.valueOf(userDB.getId()));
String token = JWTUtils.getToken(payload);
map.put("state", true);
map.put("msg", "登录成功!");
// 响应 token
map.put("token", token);
return map;
}-
顾虑
顾虑
-
-
前置路由导航守卫
1
2
3
4
5
6
7
8
9
router.beforeEach((to, from, next) => {
if (to.path === '/login') return next()
//获取 token
const tokenStr = window.localStorage.getItem('token')
if (!tokenStr) return next('/login')
next()
})
文件上传下载需求
-
要求
- 用户登录展示用户的所有文件
(文件如果是图片则在页面中显示图片) - 完成文件的下载和在线打开
(注意在线打开不计算为下载次数) - 在一张页面中文件文件的上传功能,
上传的目录要根据日期每天创建一个文件夹 (文件夹统一命名为 yyyy-MM-dd
),上传完成后要跳转到查询所有页面
- 用户登录展示用户的所有文件
-
项目规范
- 项目名字统一命名为
file_xxx
- 包名统一
com.example.xxx
com.example.mapper
com.example.service/impl
com.example.controller
com.example.entity
- 项目中的
webroot
- 建立
files
文件夹作为上传下载的总文件夹 (根据日期每天创建不同文件夹, 每天上传文件放入到不同文件夹中) - 编码格式统一采用
UTF-8
- 建立
- 项目名字统一命名为
-
数据库表
-
创建数据库
1
create database baizhi_file;
-
创建表
1
2
3
4
5
6
7
8
9
10
11
12-- 用户信息表
CREATE TABLE `t_user` (
`id` int NOT NULL COMMENT '用户id',
`username` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
-- 测试数据
INSERT INTO `baizhi_file`.`t_user` VALUES (1, 'coder-itl', 'coder-itl');
INSERT INTO `baizhi_file`.`t_user` VALUES (2, 'zhangsan', 'zhangsan');1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20-- 文件信息表
CREATE TABLE `files`
(
`id` int NOT NULL auto_increment,
`oldFileName` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '原始文件名称',
`newFileName` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '新文件名称',
`ext` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '扩展名',
`path` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件路径',
`size` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件大小',
`type` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件类型',
`isImg` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '是否是图片',
`downcounts` int DEFAULT NULL COMMENT '下载次数',
`uploadTime` datetime DEFAULT NULL COMMENT '上传时间',
`userid` int DEFAULT NULL COMMENT '用户ID',
PRIMARY KEY (`id`),
KEY `userid` (`userid`),
CONSTRAINT `files_user_id` FOREIGN KEY (`userid`) REFERENCES `t_user` (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci -
关系模型
表关系模型
-
-
显示文件列表
showAll.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户文件列表 </title>
<link rel="stylesheet" href="./myTable.css">
</head>
<body>
<h3>欢迎你: <span th:if="${session.user!=null}" th:text="${session.user.username}"></span></h3>
<h3>文件列表 </h3>
<table border="1">
<tr>
<th>ID</th>
<th>文件原始名称 </th>
<th>文件新名称 </th>
<th>文件后缀 </th>
<th>存储路径 </th>
<th>文件大小 </th>
<th>类型 </th>
<th>是否是图片 </th>
<th>下载次数 </th>
<th>上传时间 </th>
<th>用户 ID</th>
<th>操作 </th>
</tr>
<tr th:each="file,fileStat:${fileList}">
<td><span th:text="${file.id}"></span></td>
<td><span th:text="${file.oldFileName}"></span></td>
<td><span th:text="${file.newFileName}"></span></td>
<td><span th:text="${file.ext}"></span></td>
<td><span th:text="${file.path}"></span></td>
<td><span th:text="${file.size}"></span></td>
<td><span th:text="${file.type}"></span></td>
<td>
<img th:if="${file.isImg}=='是'"
th:src="${#servletContext.contextPath}+${file.path}+'/'+${file.newFileName}"/>
<span th:if="${file.isImg}!='是'" th:text="${file.isImg}"></span>
</td>
<td><span th:text="${file.downcounts}"></span></td>
<td><span th:text="${file.uploadTime}"></span></td>
<td><span th:text="${file.userid}"></span></td>
<td>
<a th:href="@{/file/download(id=${file.id})}">下载 </a>
<a th:href="@{/file/download(id=${file.id},openStyle='inline')}">在线打开 </a>
<a th:href="@{/file/delete(id=${file.id})}">删除 </a>
</td>
</tr>
</table>
<hr>
<h3>文件上传 </h3>
<form enctype="multipart/form-data" method="post" th:action="@{/file/upload}">
上传用户文件: <input name="file" type="file"/><input type="submit" value="上传文件"/>
</form>
</body>
</html> -
登录页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录 </title>
</head>
<body>
<form method="post" th:action="@{/user/login}">
用户名: <input name="username" type="text"/>
密码: <input name="password" type="password"/>
<input type="submit" value="登录">
</form>
</body>
</html> -
项目依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>baizhi-file</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>baizhi-file</name>
<description>baizhi-file</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
<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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project> -
配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38server:
port: 8080
# druid 数据源配置
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/baizhi_file?autoReconnect=true&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
username: root
password: root
initial-size: 1
min-idle: 1
max-active: 20
# 全局日期输出格式化
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
thymeleaf:
cache: false
suffix: .html
prefix: classpath:/templates/
web:
resources:
static-locations: classpath:/templates/, classpath:/static/
mybatis:
type-aliases-package: com.example.entity
mapper-locations: com/example/mapper/*.Mapper
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.example.mapper: debug
upload:
dir: E:/baizhi-file/target/classes -
mapper
-
UserMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<mapper namespace="com.example.mapper.UserMapper">
<!-- User login(User user); -->
<select id="login" parameterType="user" resultType="user">
select *
from t_user
where username = #{username}
and password = #{password}
</select>
</mapper> -
UserFileMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<mapper namespace="com.example.mapper.UserFileMapper">
<insert id="save" parameterType="userFile" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `baizhi_file`.`files` (`oldFileName`, `newFileName`, `ext`, `path`, `size`, `type`, `isImg`,
`downcounts`, `uploadTime`, `userid`)
VALUES (#{oldFileName},
#{newFileName},
#{ext},
#{path},
#{size},
#{type},
#{isImg},
#{downcounts},
#{uploadTime},
#{userid});
</insert>
<select id="findByUserId" resultType="userFile" parameterType="integer">
select *
from files
where userid = #{uid}
</select>
<select id="findById" resultType="userFile" parameterType="int">
select *
from files
where id = #{id}
</select>
<update id="update" parameterType="userFile">
update files
set downcounts =#{downcounts}
where id = #{id}
</update>
<delete id="delete">
delete
from files
where id = #{id}
</delete>
</mapper>
-
-
service
-
UserService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.example.service.impl;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public User login(User user) {
User userInfo = userMapper.login(user);
return userInfo;
}
} -
UserFileService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47package com.example.service.impl;
import com.example.entity.UserFile;
import com.example.mapper.UserFileMapper;
import com.example.service.UserFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
public class UserFileServiceImpl implements UserFileService {
private UserFileMapper userFileMapper;
public List<UserFile> findByUserId(Integer uid) {
List<UserFile> fileList = userFileMapper.findByUserId(uid);
return fileList;
}
public void save(UserFile userFile) {
// userFile.setIsImg(); 是否是图片
String isImg = userFile.getType().startsWith("image") ? "是" : "否";
userFile.setDowncounts(0).setUploadTime(new Date()).setIsImg(isImg);
userFileMapper.save(userFile);
}
public UserFile findById(Integer id) {
UserFile userFile = userFileMapper.findById(id);
return userFile;
}
public void update(UserFile userFile) {
userFileMapper.update(userFile);
}
public void delete(Integer id) {
userFileMapper.delete(id);
}
}
-
-
controller
-
UserController
1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
public class IndexController {
public String toLogin() {
// return "login"; 指向的是 templates/login.html(thymeleaf在配置文件中添加了相关配置)
return "login";
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package com.example.controller;
import com.example.entity.User;
import com.example.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpSession;
public class UserController {
private UserService userService;
public String login(User user, HttpSession session) {
User userDB = userService.login(user);
if (userDB != null) {
log.info("userDB: {}", userDB);
session.setAttribute("user", userDB);
// return "redirect:/file/showAll"; 指向的是一个请求
return "redirect:/file/showAll";
} else {
// 重定向到登录请求
return "redirect:/index";
}
}
} -
UserFileController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138package com.example.controller;
import com.example.entity.User;
import com.example.entity.UserFile;
import com.example.service.UserFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class FileController {
private UserFileService userFileService;
/**
* 展示所有文件信息
*/
public String showAll(HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
Integer userId = user.getId();
List<UserFile> fileList = userFileService.findByUserId(userId);
model.addAttribute("fileList", fileList);
return "showAll";
}
/**
* 上传文件处理 并保存文件信息到数据库中
*/
public String upload( MultipartFile file, HttpSession session)throws IOException {
// 获取登录用户 id
User user = (User) session.getAttribute("user");
Integer userId = user.getId();
// 获取原始文件名称
String oldFileName = file.getOriginalFilename();
// 新文件名称 = 原始文件名称 + 生成的新文件名称+ 后缀 (可以手写获取后缀, 也可以通过 commons-fileupload 中的工具类 (FilenameUtils))
// 获取文件后缀
String extension = "." + FilenameUtils.getExtension(oldFileName);
log.info("extension: {}", extension);
// 生成新的文件名
String newFileName = new SimpleDateFormat("yyyyMMdd").format(new Date()) + UUID.randomUUID().toString().replace("-", "") + extension;
log.info("newFileName: {}", newFileName);
// 获取文件大小
long size = file.getSize();
// 文件类型
String type = file.getContentType();
// 根据日期创建目录
String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dateDirPath = realPath + "/" + dateFormat;
File dateDir = new File(dateDirPath);
if (!dateDir.exists()) {
dateDir.mkdirs();
}
// 处理文件上传
file.transferTo(new File(dateDir, newFileName));
// 将文件信息存入数据库
UserFile userFile = new UserFile();
userFile.setOldFileName(oldFileName).setNewFileName(newFileName).setExt(extension).setSize(String.valueOf(size)).setType(type)
.setPath("/files/" + dateFormat).setUserid(userId);
userFileService.save(userFile);
return "redirect:/file/showAll";
}
/**
* 文件下载
*/
public void download(String openStyle, Integer id, HttpServletResponse response) throws IOException {
openStyle = openStyle == null ? "attachement" : openStyle;
// 获取文件信息
UserFile userFile = userFileService.findById(id);
// 只有当点击下载链接并且是附件的形式是下载次数更新
if ("attachement".equals(openStyle)) {
// 更新下载次数
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", openStyle + ";fileName=" + URLEncoder.encode(userFile.getOldFileName(), "UTF-8"));
// 获取响应输出流
ServletOutputStream os = response.getOutputStream();
// 文件拷贝
IOUtils.copy(is, os);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
/**
* 文件删除: delete
*/
public String delete(Integer id) throws FileNotFoundException {
// 根据 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/showAll";
}
}
-
-
整体效果
文件上传下载
Table-美化
-
css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45table {
border-collapse: collapse;
width: 100%;
border: 1px solid #c6c6c6 ;
margin-bottom: 20px;
}
th {
border-collapse: collapse;
border-right: 1px solid #c6c6c6 ;
border-bottom: 1px solid #c6c6c6 ;
background-color: #ddeeff ;
padding: 5px 9px;
font-size: 14px;
font-weight: normal;
text-align: center;
}
td {
border-collapse: collapse;
border-right: 1px solid #c6c6c6 ;
border-bottom: 1px solid #c6c6c6 ;
padding: 5px 9px;
font-size: 12px;
font-weight: normal;
text-align: center;
word-break: break-all;
}
table tr:nth-child(odd) {
background-color: #fff ;
}
span {
color: darkorange;
}
td img {
width: 100px;
height: 10%;
}
table tr:nth-child(even) {
background-color: #f8f8f8 ;
}
commons-fileupload
-
处理下载流复制
1
2
3
4// 文件拷贝
IOUtils.copy(is, os);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);-
解决的问题
1
2
3
4
5
6
7
8
9
10
11// 传统写法
int len;
byte[] b = new byte[1024];
while (true){
len = is.read();
if(len==-1) break;
os.write(b,0,len);
}
// 释放资源
is.close();
os.close();IO
使用 IOUtils
,文件操作使用FileUtils
-
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 coder-itl!
评论