碰到个业务需求,表单项有图片或文件上传需求,并且要求跟随表单数据一起走...
上传用element的el-upload组件
表单数据带着文件时,表单上传格式需要变动,需要使用 FormData 对象 ,而文件需要设置手动上传,并把获取到的文件添加到表单对象中,并把其他对单数据也逐步添加到表单对象
先介绍获取上传文件的方式,上传部分代码:
文章图片
上传部分样式:
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
上传组件 action 为上传地址,这里是跟随表单走,所以设置为空,但action 必须有!!!,另外设置自动上传为 false,也可以设置多文件,或者列表形式上传或者设置文件格式和大小拦截,这里重点是
:http-request="uploadImg"
这个属性绑定一个方法就是自定义上传方法,我们就是通过这个方法获取准备上传的文件,其他事件获取的文件用于上传时有问题。
注意:这个自定义方法是在组件使用submit后才会触发(大坑,折腾了好久才发现)
【vue|vue el-upload 组件上传的 文件跟随表单数据 发送后台保存】上传前文件格式和大小判定代码:
beforeAvatarUpload (file) {
const isJPG = file.type === 'image/jpeg' || 'image/png' || 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG,PNG,JPEG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
},
靠这个方法绑定change事件实现自定义图片回显:
imgSaveToUrl (event) {
if (this.beforeAvatarUpload(event)) {
var URL = null
if (window.createObjectURL != undefined) {
// basic
URL = window.createObjectURL(event.raw)
} else if (window.URL != undefined) {
// mozilla(firefox)
URL = window.URL.createObjectURL(event.raw)
} else if (window.webkitURL != undefined) {
// webkit or chrome
URL = window.webkitURL.createObjectURL(event.raw)
}
this.dataForm.headUrl = URL
}
},
其他详细看代码:
//自定义上传方法,使用上传组件的submit()后才会触发以获取文件实体
uploadImg (param) {
this.img = param.file
},
// 表单提交
dataFormSubmitHandle: debounce(
function () {
this.$refs.dataForm.validate((valid) => {
if (!valid) {
return false
}
this.$refs.uploadImage.submit() //必须使用此方法才会触发自定义上传方法以获取文件对象
var form = new FormData() //携带文件必须使用此对象
if (this.img) {
form.append("file", this.img) 把文件实体添加到表单对象
}
let obj = {
id: this.dataForm.id || undefined,
username: this.dataForm.username,
password: this.dataForm.password,
confirmPassword: this.dataForm.confirmPassword,
realName: this.dataForm.realName,
idCard: this.dataForm.idCard,
gender: this.dataForm.gender,
email: this.dataForm.email,
mobile: this.dataForm.mobile,
mobile2: this.dataForm.mobile2,
telephone: this.dataForm.telephone,
wechat: this.dataForm.wechat,
passportNum: this.dataForm.passportNum,
appNum: this.dataForm.appNum,
status: this.dataForm.status,
appStatus: this.dataForm.appStatus,
spell: this.dataForm.spell,
pinyin: this.dataForm.pinyin,
sort: this.dataForm.sort,
superAdmin: this.dataForm.superAdmin,
createDate: null,
headUrl: this.dataForm.headUrl,
masterDeptIdArr: this.dataForm.masterDeptIdArr,
masterJobId: this.dataForm.masterJobId,
slaveDeptJobList: this.dataForm.slaveDeptJobList
}
//序列化其他数据为json添加到表单对象,后台反序列化获取对象实体,也可以单个append(),后台直接用对象取,如果一次性添加而不序列化会出错
form.append("dto", JSON.stringify(obj)) api.saveUser(form)
.then((res) => {
this.$message({
message: this.$t('prompt.success'),
type: 'success',
duration: 500,
onClose: () => {
this.visible = false
this.$emit('refreshDataList')
},
})
})
.catch(() => { })
})
},
1000,
{ leading: true, trailing: false }
),
后台接收:
@PostMapping
@ApiOperation("保存")
@LogOperation("保存")
@RequiresPermissions("sys:user:save")
public Result save(@RequestParam(required = false,name = "file") MultipartFile file, @RequestParam(name = "dto") String dto){
JSONObject jsonObject = JSONObject.parseObject(dto);
SysUserDTO sysUserDTO = JSONObject.parseObject(dto, SysUserDTO.class);
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
if (file != null) {
MultipartFile []files =new MultipartFile[1];
files[0] = file;
String headUrl = FileUtils.saveFile(files);
sysUserDTO.setHeadUrl(headUrl);
}
sysUserService.save(sysUserDTO);
return new Result();
}
推荐阅读
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- 前端开发|Vue2.x API 学习
- vue|Vue面试常用详细总结
- vue|电商后台管理系统(vue+python|node.js)
- 腾讯TEG实习|腾讯实习——Vue解决跨域请求
- Vue|vue-router 详解
- vue|vue3替代vuex的框架piniajs实例教程
- Vue|Vue3.0的插槽是如何实现的()
- 前端|面试官(谈谈Vue和React的区别())