Sprinboot +vue 图片上传前后端与遇到坑
- 工具
- 需求
- 流程
工具
1.spring boot
2.vue
需求
1.前端传图片到后台进行保存同时存到数据库下次看会回显(单张)。
流程
1.先调用:before-upload钩子函数,看看是否符合上传图片。
2.可以都话会自动调用action直接到后台对应的控制器执行方法。
3.成功后会自动调用成功勾子函数。
4.如果你选择传送多张时候还进行移除那么移除函数的fileList包含了最终图片信息。
下面直接看代码
vue
具体详情可以查看官网:https://element.eleme.cn/#/zh-CN/component/upload
<el-form-item label="头像">
<el-upload class="avatar-uploader" :action="action" :show-file-list="true" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload" :on-error='handleAvatarFail' :before-remove='handleAvatarRemove' :limit="1">
<img v-if="administrator.picture" :src="administrator.picture" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
js
let api = "/api"; //表示你配置跨域时候的api。
let http = "http://192.168.101.32:99/image/"; //用于第二次回显时候的一个地址访问路径
data() {
return {
action: api + "upload", //上传图片后台地址
}
},
methods: {
handleAvatarSuccess(res, file) {
// this.administrator.picture = URL.createObjectURL(file.raw); //最好不要用这个因为到后面会发现第二次回显会有问题。报404,刚开始我也是用这个
this.administrator.picture =http+res.data.imageUid;
this.administrator.imageUid=res.data.imageUid;
if (res.stavodevi.code == 200) {
Message({
message: "上传成功",
duration: 1.5 * 1000,
type: 'success',
})
} else {
Message({
message: "上传失败,请稍后重试",
duration: 1.5 * 1000,
type: 'error',
})
}
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
message.error('上传头像图片只能是 JPG 格式!');
return;
}
if (!isLt2M) {
message.error('上传头像图片大小不能超过 2MB!');
return;
}
this.files = file;
return isJPG && isLt2M;
},
}
后端
控制器
//就是前端action调用的控制器
@PostMapping("upload")
public Reobj<administrator> upload(HttpServletRequest request, HttpServletResponse response) {
Reobj<administrator> reobj = new Reobj<administrator>();
administrator adm = new administrator();
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;//这里可能会报错的
Iterator<String> iter = multiRequest.getFileNames();
while (iter.hasNext()) {
MultipartFile file = multiRequest.getFile(iter.next().toString());
if (file != null) {
String tmp = file.getOriginalFilename();
String name = IdGen.uuid() + "." + tmp.substring(tmp.lastIndexOf(".") + 1);
String path=url+name; //url表示为我的磁盘存放图片地址c://image。
adm.setPicture(path); //表示文件名字
adm.setImageUid(name); //表示文件进行格式化后唯一标识
if (!new File(url).exists()) {
new File(url).mkdirs();
}
try {
file.transferTo(new File(path));
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
reobj.setData(adm);
reobj.setStavodevi(Status_CodeEntity.SUCCESS);
} else {
}
}
}
return reobj;
}
辅助类
便于对uuid数据进行一个重新编译也便于保存起来。
public class IdGen {
public static String uuid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
}
这个时候开始填坑了
一般会出现request无法转换MultipartHttpServletRequest 错误等。
原因:
1:你的前端没有配置好请求头信息为multipart/form-data;
2:后端无法解析或者文件太大了导致不能上传等等。
我使用的是element的el-upload肯定封装的;所以肯定是第二种的问题。
解决方案:
我自己定义一个拦截器
@Configuration
public class CommonConfig {
@Bean(name = "multipartResolver")//通过在主程序入口加载即可
public MultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setResolveLazily(true);//resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
resolver.setMaxInMemorySize(40960);
resolver.setMaxUploadSize(50*1024*1024);//上传文件大小 50M 50*1024*1024
return resolver;
}
}
主程序上写上
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@SpringBootApplication
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@MapperScan("jee.moudles.**/*.dao")
public class ApplicationMain {
public static void main(String[] args) {
SpringApplication.run(ApplicationMain.class, args);
}
}
然后在application.yml上面加上一句话
spring
http
multipart
enabled: true
现在就可以上传成功并且不报错了;但是你可能第二次回显报错说什么图片404
分析
404是找不到文件,回想一下以前用Tomcat时候出现图片404问题就是路径问题咯,但是springboot是内嵌tomcat我们不好去更改一些配置,再说上传时候我们是把图片存到了磁盘上面,所以现在缺个链接把磁盘上面的图片变成类似于放在Tomcat里面。
加一个配置类
@Configuration
public class MyPicConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registy) {
registy.addResourceHandler("/image/**").addResourceLocations("file:///C:/image/"); //第一个image表示前端地址后面的值,第二个是我的本地地址
}
}
如果上传时候会报错:org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request
则在application.yml中加上:
spring
http
multipart
enabled: true
location: /data/upload_tmp //加上这句,原理:建立一个存储临时区
此时您就可以使用了,大功告成。