SpringBoot3 +vue3 实现文件上传和下载

文件下载

新建一个fileController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 文件下载
* 下载路径: http://localhost:9999/file/download/1.png
*/
@GetMapping("/download/{fileName}")
public void download(@PathVariable String fileName, HttpServletResponse response) throws Exception {
// 找到文件的位置
String filePath = System.getProperty("user.dir")+ "/files/";// 获取到当前项目的根路径 (code2025的绝对路径)
String realPath = filePath + fileName;
boolean exist = FileUtil.exist(realPath);
if(!exist) {
throw new CustomerException("文件不存在");
}
//读取文件的字节流
byte[] bytes = FileUtil.readBytes(realPath);
ServletOutputStream os = response.getOutputStream();
// 输出流对象把文件写出到客户端
os.write(bytes);
os.flush();
os.close();
}

以附件的形式下载(可忽略)

1
2
response.addHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName));
response.setContentType("application/octet-stream");

接口放行,不鉴权

1
2
3
4
5
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor).addPathPatterns("/**")
.excludePathPatterns("/login","/register","/files/download/**");
}

访问成功!

image-20250304154808956.png

纯文本,pdf,也是可以的

浏览器根据文件类型来判断能不能打开

文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
public Result upload(@RequestParam("file")MultipartFile file) throws Exception {
// 找到文件的位置
String filePath = System.getProperty("user.dir")+ "/files/";// 获取到当前项目的根路径 (code2025的绝对路径)
if(FileUtil.isDirectory(filePath)){
FileUtil.mkdir(filePath);
}
byte[] bytes = file.getBytes();
String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); //文件的原始名称
//写入文件
FileUtil.writeBytes(bytes,filePath+fileName);
String url = "http://localhost:9999/files/download/" +fileName;
return Result.success(url);
}

在数据库中的user表哪里新增字段avatar

前端对接

文件上传到数据库存储额是一串url链接的字符串

表单上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<el-form-item prop="avatar" label="头像" >
<el-upload
action="http://localhost:9999/files/upload"
:headers="{ token: data.user.token }"
:on-success="handleFileSuccess"
list-type="picture"
>
<el-button type="primary">上传头像</el-button>
</el-upload>
</el-form-item>


const handleFileSuccess = (res) => {
data.form.avatar = res.data
}

表格显示图片

1
2
3
4
5
6
7
<el-table-column  label="头像">
<template #default="scope">
<el-image v-if="scope.row.avatar" :preview-src-list="[scope.row.avatar]"
:src="scope.row.avatar"
style="width: 40px; height: 40px;border-radius: 50%;display: block;" />
</template>
</el-table-column>

图片预览效果不理想

image-20250304182216239.png

加上 :preview-teleported="true" 即可解决~

1
2
3
4
5
6
7
<el-table-column  label="头像">
<template #default="scope">
<el-image v-if="scope.row.avatar" :preview-src-list="[scope.row.avatar]"
:src="scope.row.avatar" :preview-teleported="true"
style="width: 40px; height: 40px;border-radius: 50%;display: block;" />
</template>
</el-table-column>