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   //加上这句,原理:建立一个存储临时区

此时您就可以使用了,大功告成。