SpringBoot文件上传
文件上传的本质
文件上传的流程,相当于是复制,是读取了要上传文件的二进制流,并把这个二进制流的信息复制给服务器指定路径的另一个文件
文件上传的细节点
-
在服务器中需要有专门的目录来存放上传路径 ,在新的上传请求传来时,必应判断该上传路径是否存在,若不存在 ,则需要先创建该上传目录。
-
在服务器中的文件,为了防止上传文件的名称重复(防止重复提交同一文件),从而产生冲突等问题,应用 UUID 来生成随机 ID 为新文件命名
-
文件上传应当将上传至服务器的url地址保存在数据库中
获取原文件名称
在前端向后端发起上传请求时,传参中必然带有文件信息,此时在 Controller 层对应的接口中会接收到 MultipartFile 类型的 file
通过以下代码可获取原文件的信息:
//原文件名称
String OriginFileName = file.getOriginalFilename();
//原文件文件名最大长度
int fileNamelength = file.getOriginalFilename().length()
获取新文件路径(名称)
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
//获得文件名后缀
String extension = getExtension(file);
//拼接上时间
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
}
为什么要拼接上时间,是因为window类似mysql也有自己的索引规则,通过时间来查找,能减轻搜索压力
将远程文件存入本地
假设,存放新文件的变量名称为 newFile ,远程文件变量名称为 oldFile
则可通过以下代码将远程文件保存至本地文件中:
oldFile.transferTo(newFile);
修改上传文件类型
upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
其中DEFAULT_ALLOWED_EXTENSION是上传时候默认携带的一个参数,存储了一个集合(文件类型)
可以发现这里面没有视频的类型,要想该上传可以通过视频类型的文件,可以在这个集合上加上视频对应的类型
案例
前端采取ElementUI上传的组件
这个项目上传是需要验证权限的,所以请求时候在请求头携带了一个认证的参数
<template>
<!-- 普通单个文件上传-->
<div class="component-upload-image">
<el-upload v-if="chooseFlag ==0"
drag
:action="uploadImgUrl"
:on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
</template>
<script>
import { getToken } from '@/utils/auth';
export default {
name:"Upload",
components: {},
data() {
return {
headers: {
Authorization: "Bearer " + getToken(),
},
uploadUrlPath: "没有文件上传",
};
},
props: {
value: {
type: String,
default: "",
},
chooseFlag: {
value: Number,
default: 0,
},
uploadImgUrl: {
type: String,
default: "/v1/admin/common/upload", // 上传的图片服务器地址
},
},
methods: {
handleUploadSuccess(res) {
this.uploadUrlPath = JSON.stringify(res);
this.loading.close();
//把uploadUrlPath封装在upload-event,别的页面可以通过组件upload-event来调用这个属性
this.$emit("upload-event",this.uploadUrlPath);
},
handleBeforeUpload() {
this.loading = this.$loading({
lock: true,
text: "上传中",
background: "rgba(0, 0, 0, 0.7)",
});
},
handleUploadError() {
this.$message({
type: "error",
message: "上传失败",
});
this.loading.close();
},
},
watch: {},
};
</script>
<style scoped lang="scss">
.avatar {
width: 100%;
height: 100%;
}
</style>
后端
CommonController
这里处理上传后的文件名称和请求路径进行一个拼接
public class CommonController {
@Autowired
private ServerConfig serverConfig;
/**
* 通用上传请求
*/
@PostMapping("/upload")
public ResultJson uploadFile(MultipartFile file) throws Exception {
try {
// 上传文件路径(配置文件中的)
String filePath = NiuaConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.