vue3+springboot上传文件
1.上传文件
前端el-upload 使用fileList接收一个文件列表,data为上传文件时,携带的数据
<el-upload
class="upload-video"
v-model:file-list="fileList"
ref="uploadRef"
multiple
accept=".mp4, .webm"
:disabled="buttonDisabled"
:data="data"
:auto-upload="false"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-success="submitFormSuccess"
:before-remove="beforeRemove"
:on-change="handleFileChange"
>
<el-button :disabled="buttonDisabled" class="upload-button" type="primary"
>点击上传</el-button
>
<template #tip>
<div v-if="buttonDisabled" class="el-upload__tip" style="color: red">
提示:可以更改名称和描述,不可更改视频原文件!
</div>
<div v-else class="el-upload__tip" style="color: red">
提示:仅允许导入 mp4、webm格式文件!!!
</div>
</template>
</el-upload>
然后调用axios,发送请求,注意'Content-Type': 'multipart/form-data'
const res = await axios.post(
'url',
{
files: fileList.value,
name: data.value.name,
description: data.value.description
},
{
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}
}
)
console.log(res)
spring boot后端处理
@PostMapping("/uploadVideos")
@Operation(summary = "上传视频")
public CommonResult<Long> uploadVideos(@RequestParam("files[]") MultipartFile[] files, String name, String description, String sid, byte detectType) {
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
//获取文件后缀
String suffixName = UploadUtil.getUploadPath(file);
//生成新文件名称
String newFileName = UploadUtil.getNewFileName(suffixName);
//保存文件
File fileSave = new File(UploadUtil.getNewUploadPath(UploadUtil.VIDEO_PATH,newFileName));
boolean state = UploadUtil.saveUpload(file, fileSave);
if (state) {
// 处理data逻辑
} else {
// 如果保存失败,就报错
return error(99,"上传视频失败");
}
}
return success(Long.valueOf("0"));
}
其中UploadUtil
public class UploadUtil {
public static String FILE_PATH;
public static String IMAGE_PATH;
public static String VIDEO_PATH;
public static boolean dev = false;
static {
if(dev){
FILE_PATH = "/upload/file/";
IMAGE_PATH = "/upload/picture/";
VIDEO_PATH = "/upload/video/";
}else {
FILE_PATH = "D:/Project/****/files/";
IMAGE_PATH = "D:/Project/****/imgs/";
VIDEO_PATH = "D:/Project/****/videos/";
}
}
/**
* 返回文件后缀
*
* @param file
* @return
*/
public static String getUploadPath(MultipartFile file) {
String fileName = file.getOriginalFilename();//获取原文件名
int index = fileName.indexOf(".");
return fileName.substring(index, fileName.length());
}
/**
* 保存图片
*
* @param mfile
* @param file
* @return
*/
public static boolean saveUpload(MultipartFile mfile, File file) {
//查看文件夹是否存在,不存在则创建
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
//使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错
mfile.transferTo(file);
return true;
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 新文件名
*
* @param suffix
* @return
*/
public static String getNewFileName(String suffix) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String date = sdf.format(new Date());
return date + UUID.randomUUID() + suffix;
}
/**
* 返回图片保存地址
*
* @param name
* @return
*/
public static String getNewUploadPath(String path,String name) {
return path + name;
}
}
问题(1)使用e-upload批量上传文件时,传到后端的数据变为 file: [object object],或者后端只能拿到一个文件数据
使用一个空的files,来接收fileList数据,然后再传入后端==》解决
const files = []
for (let i = 0; i < fileList.value.length; i++) {
files.push(fileList.value[i].raw)
}
补充:
- 文件上传类型判断
/**
* @description 文件上传之前判断
* @param rawFile 上传的文件
* */
const videoTypeList = ['.mp4', '.webm']
const handleFileChange: UploadProps['onChange'] = (rawFile) => {
const videoType = rawFile.name.substring(rawFile.name.lastIndexOf('.'))
if (!videoTypeList.includes(videoType)) {
ElNotification({
title: '温馨提示',
message: '上传视频不符合所需的格式!',
type: 'warning'
})
fileList.value.pop() // 不符合条件,弹出最后一个元素
return false
}
return true
}
- 校验前端数据,输入不能为空
表单使用:rules="formRules"
const formRules = reactive({
name: [{ required: true, message: '视频名称不能为空', trigger: 'blur' }],
description: [{ required: true, message: '视频描述不能为空', trigger: 'blur' }]
})