/**
* @description 文件相关的接口
*/
@RestController
@RequestMapping("/files")
public class FileController {
// System.getProperty("user.dir") 获取到你当前这个项目的根路径
// 文件上传的目录路径
private static final String filePath = System.getProperty("user.dir") + "/files/";
/**
* 文件上传
*/
@PostMapping("/upload")
public Result upload(MultipartFile file) { // 文件流的形式接收前端发送过来的文件
String originalFilename = file.getOriginalFilename(); // xxx.jpg
if (!FileUtil.isDirectory(filePath)) { // 如果目录不存在,需要先创建目录
FileUtil.mkdir(filePath); // 创建一个files目录
}
// 提供文件存储的完整路径
// 给文件名加一个唯一的标识
String fileName = System.currentTimeMillis() + "_"+ originalFilename; // 例如像15959482362_xxx.jpg
String realPath = filePath + fileName; // 完整的文件路径
try {
FileUtil.writeBytes(file.getBytes(), realPath);
} catch (IOException e) {
e.printStackTrace();
throw new CustomException("500", "文件上传失败");
}
// 返回一个网络连接
// http://localhost:9090/files/download/xxxx/jpg
String url = "http://localhost:9090/files/download/" + fileName;
return Result.success(url);
}
/**
* 文件下载
*/
@GetMapping("/download/{fileName}")
public void download(@PathVariable String fileName, HttpServletResponse response) {
try {
// 设置响应头,指示浏览器下载文件
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
// 设置响应内容类型为二进制流
response.setContentType("application/octet-stream");
ServletOutputStream os = response.getOutputStream();
String realPath = filePath + fileName; // 完整的文件路径
// 获取到文件的字节数组
byte[] bytes = FileUtil.readBytes(realPath);
os.write(bytes);
os.flush();
os.close();
} catch (IOException e) {
throw new CustomException("500", "文件下载失败");
}
}
}中文的文件名在下载的时候可能会有编码错误,解决方式如下
// 设置响应头,指示浏览器下载文件
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
// 设置响应内容类型为二进制流
response.setContentType("application/octet-stream");用户头像
upload组件代码
<div style="display: flex; justify-content: center; margin-bottom: 20px">
<el-upload
class="avatar-uploader"
action="http://localhost:9090/files/upload" //这里是自己后端文件上传的路径
:show-file-list="false"
:on-success="handleAvatarSuccess"
>
<img v-if="data.form.avatar" :src="data.form.avatar" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</div>回调函数
const handleAvatarSuccess = (res) => {
console.log(res.data)
data.form.avatar = res.data
}<style scoped>
.avatar-uploader .avatar {
width: 120px;
height: 120px;
display: block;
}
</style>
<style>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 50%;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
text-align: center;
}
</style><el-table-column label="头像" prop="avatar">
<template #default="scope">
<el-image
v-if="scope.row.avatar"
style="width: 50px; height: 50px; border-radius: 50%; display: block;"
:src="scope.row.avatar">
</el-image>
</template>
</el-table-column><el-form-item label="头像" prop="username">
<el-upload
action="http://localhost:9090/files/upload"
list-type="picture"
:on-success="handleAvatarSuccess">
<el-button type="primary">上传头像</el-button>
</el-upload>
</el-form-item>
const handleAvatarSuccess = (res) => {
console.log(res.data)
data.form.avatar = res.data
}<div style="display: flex; align-items: center; padding-right: 10px">
<img :src="data.user.avatar || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'" width="40 px" height="40px" style="border-radius: 50%"/>
<span style="color: white; margin-left: 5px">{{data.user.name}}</span>
</div>