前端Vue利用element组件库的el-upload传图片
参考:
需求: 实现一个添加走失宠物信息的功能,包括文字信息(利用表单组件)和宠物图片(利用上传组件),这里我将图片上传组件写进表单组件里了,我想要在点击表单组件的提交按钮时,将图片和文字一起上传给后台。
问题: 现在的问题是element的上传组件会自动提交到action里设置的地址,我选择一张他就提交一张上去了。所以需要我自定义一下。
//上面还有个文字表单组件,这里主要是讲图片上传,表单代码就省略了
<div class="up-picture-box">
<el-upload
ref="imgForm"
:auto-upload="false"//取消自动上传
:http-request="upLoadFile"//自定义的上传方法,会覆盖默认的上传行为,默认上传行为是选择一张图片就上传一张,直接上传到action里的地址,
//但我需求是选择多张图片后和表单信息一起dispatch Action再传给后台接口,
//所以自定义上传方式就是将图片一张一张的存进formData的file字段里,等待提交表单的时候将formData传给后台
action=""//因为设置了不自动上传和自定义上传方式,设置了上传地址,所以不需要这个图片上传地址了
:multiple="multiple"
:limit="Number(6)"//限制图片数量
list-type="picture-card"
:on-preview="handlePictureCardPreview">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
<el-form-item style="margin-left: 180px;">
<el-button type="primary" @click="submitForm('ruleForm')" >提交</el-button>//这是表单组件的提交按钮
<el-button @click="loseView = false">取消</el-button>
</el-form-item>
点击表单提交按钮,创建formData,将表单信息封装进formData中,然后运行 this.$refs.imgForm.submit();
触发上传组件提交,开始上传图片,运行自定义上传方法upLoadFile()
,将图片一张一张的存进fromData的file字段中。(有多少图片就调用多少次upLoadFile()方法)完成后将这个formData对象通过post请求上传给后台,代码如下:
首先在data中定义:formData:""
upLoadFile(file){
this.formData.append('file',file.file)
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {//校验表单
if (valid) {//格式正确才能提交表单
this.formData = new FormData;
this.formData.append('title', this.ruleForm.title);
this.formData.append('kind', this.ruleForm.kind);
this.formData.append('name', this.ruleForm.name);
this.formData.append('time', this.ruleForm.time);
this.formData.append('address', this.ruleForm.address);
this.formData.append('detail', this.ruleForm.detail);
this.formData.append('telephone', this.ruleForm.telephone);
this.$refs.imgForm.submit();//触发上传图片,开始一张一张的执行每个图片的http-request,遍历完成后此时的formData中的‘file’对应的就是待上传的图片对象数组了
this.$store.dispatch('addLOFPetsAction', {LoseOrFind: this.LoseOrFind, petKind: this.petKind, formData: this.formData});
} else {
alert("请将宠物丢失信息填写完整!");
}
})
},
在store中发送post请求:addLOFPetsAction()方法:
addLOFPetsAction(context,selected){
switch (selected.LoseOrFind){
case 'lose':switch (selected.petKind){
case 'dogs':axios.post('/addLoseDog',selected.formData,{headers: {'Content-Type': 'multipart/form-data'}}).then((res)=>{window.console.log("返回的id"+res.data);});break;
case 'cats':……
case 'find':switch (selected.petKind){
case 'dogs':……
case 'cats':……
}
}
}
查看请求:
后台接收图片并存进数据库:
(上传的图片保存在本地,存进数据库的只是图片的url地址,不是真正的图片)
controller类:
@CrossOrigin//解决跨域问题
@PostMapping(value = "/api/addLoseDog")
@ResponseBody
public int upDogLoseImg(@RequestParam("title") String title,@RequestParam("kind") String kind,@RequestParam("name") String name,@RequestParam("time") String time,@RequestParam("address") String address,@RequestParam("detail") String detail,@RequestParam("telephone") String telephone,@RequestParam("file") MultipartFile[] file) {
String imgString = "";//用来将多个图片地址连接起来存进数据库(因为数据库不能存数组)
System.out.println("传了多少张:"+file.length);
for (int i = 0; i < file.length; i++) {
if (file[i].isEmpty()) {
throw new NullPointerException("文件为空");
}
String fileName = file[i].getOriginalFilename(); // 获取文件名
String suffixName = fileName.substring(fileName.lastIndexOf("."));// 获取文件的后缀名
String path = "E://IdeaProjects//my-server-save-img//";// 文件上传后存储的位置
//为防止文件重名被覆盖,为每个文件都生成不同的名字
UUID uuid = UUID.randomUUID();//生成一个唯一标识符
String newFileName = uuid.toString().replaceAll("-", "") + suffixName;
System.out.println("新文件名newFileName:" + newFileName);
File dir = new File(path, newFileName);//创建文件流,对文件操作
File filepath = new File(path);
if (!filepath.exists()) {
filepath.mkdirs();
}
try {
file[i].transferTo(dir);//将文件 传送到之前创建的文件流(把图片写进去)
} catch (IOException e) {
e.printStackTrace();
}
if (imgString.equals(""))
imgString = imgString+"http://localhost:8008/myimg/"+newFileName;//这里的myimg路径是要自己配置的,下面再介绍
else
imgString = imgString + "," +"http://localhost:8008/myimg/" + newFileName;
}
FindPetBean findPetBean = new FindPetBean();//把提交的表单封装进bean
findPetBean.setTitle(title);
findPetBean.setKind(kind);
findPetBean.setName(name);
findPetBean.setTime(time);
findPetBean.setAddress(address);
findPetBean.setPicture(imgString);
findPetBean.setTelephone(telephone);
findPetBean.setDetail(detail);
return findService.addLoseDog(findPetBean);//把bean存进数据库
}
关于上面那个路径:"http://localhost:8008/myimg/"+newFileName;
是我要在数据库表的图片字段存放的内容,即图片的url,这样前端获取这个图片链接后直接就可访问到图片,为什么前端通过这个链接就可以直接访问到我通过后端存在本地的图片呢?因为我在后端中做了配置,自定义静态资源映射目录,配置类如下:
参考
package com.example.myspringbootdemo.myConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/myimg/**").addResourceLocations("file:E:/IdeaProjects/my-server-save-img/");
//addResoureHandler:指的是对外暴露的访问路径。addResourceLocations:指的是内部文件放置的目录。设置后,在浏览器窗口输入http://localhost:8008/myimg/文件名,就可以访问到本地地址为E:/IdeaProjects/my-server-save-img/文件名 的文件了。
super.addResourceHandlers(registry);
}
}
配置好后就可以访问图片了~