实现例如用户注册信息填写,商品发布等等需求时,通常会有需要上传图片的需求。这个时候我们可以使用Element-UI的el-upload组件进行图片上传。
<el-upload
action="https://jsonplaceholder.typicode.com/posts/"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>
export default {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
}
}
}
</script>
但是我们如果直接将这段代码放上去使用,不修改的话就会出现几个问题。图片一旦选择就直接通过后端上传到了数据库,如果用户想要修改上传的图片,那旧图片却已经在数据库中存在。无法实现图片与表单中的其他数据一起上传的需求。
所以为了实现图片跟随表单上传的需求,我们需要先关闭el-upload的自动上传,再将图片信息上传到一个FormData 对象中,当提交表单的时候,先将这个对象上传到后端,后端将图像存储到数据库中,并返回相应的图片信息,前端获取到这些图片信息后,赋值到相应的表单数据,再上传整张表单。
前端:
<el-form-item label="图片" prop="img">
<el-input v-model="ruleForm.img" v-if="false"></el-input>
<el-upload
action=""
ref="uploadimg"
list-type="picture-card"
:auto-upload="false"
:data="ruleForm"
:file-list="ruleForm.img"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-change="handleChange"
:http-request="uploadFile">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="adoptFormdialogVisible">
<img width="100%" :src="adoptFormdialogImageUrl" alt="">
</el-dialog>
</el-form-item>
<script>
export default {
name: "Tab",
data() {
return {
dialogFormVisible: false,
adoptFormdialogVisible: false,
adoptFormdialogImageUrl:'',
classify: [],
hasLogin: false,
dialogFormVisible: false,
ruleForm: {
id: '',
name: '',
introduce: '',
price: '',
banner: '',
classify_id: '',
status: '1',
user_id: '1'
},
rules: {
name: [
{ required: true, message: '请输入标题', trigger: 'blur' },
{ min: 3, max: 25, message: '长度在 3 到 25 个字符', trigger: 'blur' }
],
introduce: [
{ required: true, message: '请输入摘要', trigger: 'blur' }
],
price: [
{ required: true, message: '请输入价格,自动保留两位小数', trigger: 'blur' }
],
classify: [
{ required: true, message: '请选择商品类别', trigger: 'blur' }
]
},
activeTab: 'first',
showHeader: false,
formData:''
};
},
methods: {
submitForm(formName){// 用户点击上传表单后
this.$refs[formName].validate((valid) => {
if (valid) {
this.formData = new FormData()
this.$refs.uploadimg.submit();
// 先上传图片,图片存在formData中
this.$axios.post("/file/upLoad", this.formData).then( res =>{
console.log(res)
this.ruleForm.banner = res.data.data // 返回图片相关信息,例如图片名称
// 表单上传
this.$axios.post("/goods/saveGoods", this.ruleForm).then( res=> {
if(res.data.code == 200){
this.$message({
message: res.data.msg,
type: 'success'
});
//传值给父组件关闭弹框
this.$emit("func", false)
this.$refs[formName].resetFields();
}else{
this.$message.error(res.data.msg);
}
this.dialogFormVisible = false
})
}).catch( res=>{
console.log(res)
})
} else {
console.log('error submit!!');
return false;
}
});
}
</script>
图片上传工具类:
public class UploadUtils {
// 项目根路径下的目录 -- SpringBoot static 目录相当于是根路径下(SpringBoot 默认)
public final static String IMG_PATH_PREFIX = "static/imgs";
public static File getImgDirFile(){
// 构建上传文件的存放 "文件夹" 路径
String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
File fileDir = new File(fileDirPath);
if(!fileDir.exists()){
// 递归生成文件夹
fileDir.mkdirs();
}
return fileDir;
}
}
图片上传接口:修改图片名称,避免图片名称冲突导致不可上传图片,并返回图片名称
@RestController
@RequestMapping("/file")
public class FileController {
@PostMapping(value = "/upLoad")
@ResponseBody
public Result upLoad(@RequestParam(value = "file", required = false) MultipartFile[] multipartFiles){
StringBuffer sb = new StringBuffer();
File fileDir = UploadUtils.getImgDirFile();
try {
// 不传图片,此处捕获空指针异常,代码照常运行
for(int x = 0; x<multipartFiles.length; x++){
MultipartFile uploadFile = multipartFiles[x];
// 存储图片
File uploadDir = new File(fileDir.getAbsolutePath() + File.separator);
if ( uploadFile != null) {
//获得上传文件的文件名
String oldName = uploadFile.getOriginalFilename();
System.out.println("[上传的文件名]:" + oldName);
String uuid = UUID.randomUUID().toString().replace("-", "");
String newName = uuid + oldName;
System.out.println("[新文件名]:" + newName);
if (sb.toString().equals("")){
sb.append(newName);
}else {
sb.append("|" + newName);
}
System.out.println(sb.toString());
//我的文件保存在static目录下的avatar/user
File pic = new File(uploadDir, newName);
try {
//保存图片
uploadFile.transferTo(pic);
//返回成功结果,附带文件的相对路径
}catch (IOException e) {
System.out.println("=====捕获异常=====");
e.printStackTrace();
}
}
}
}catch (NullPointerException e){
System.out.println("=====捕获异常=====");
e.printStackTrace();
}
// 存储其它数据
return Result.succ(sb.toString());
}
}
表单上传接口:java
@PostMapping("saveGoods")
public Result saveGoods(@RequestBody Goods goods) {
goodsService.saveGoods(goods);
return Result.succ("成功");
}