【SpringBoot与Vue实现文件上传】 MultipartFile与SysLog冲突(大坑)

html

这里用的组件是 ant-design-vue

<a-input type="file" @change="upload_photo($event)" accept="image/*"></a-input>

js

       //input触发事件
       upload_photo: function(e){
        let file = e.target.files[0];
        console.log(file);

        this.uploadFile(file);

       },

      //图片上传
      uploadFile(file){

        let httpurl = this.url.uploadFile;  //后端接口地址
        var formData = new FormData();
        formData.append('file',file);

        axios.post(httpurl,formData).then((response) => {
          console.log('响应');
          console.log(response);
          this.$message.success('成功');
        }).catch(function (err) {
          console.log('失败');
          console.log(err);    //捕获异常
          this.$message.warning('失败');
        }).finally(()=>{

        });

      },

后端 controller

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	 public Map<String, String> uploadPhoto(MultipartFile file, HttpServletRequest request) throws IOException, ServletException {
	 	 Map<String, String> ret = new HashMap<String, String>();
		 logger.info("getName = "+file.getName());
		 logger.info("getOriginalFilename = "+file.getOriginalFilename());
		 ret.put("type", "success");
		 return ret;
	 }

运行之后后端确实能接收到了文件,文件名和原文件名都打印出来了,但是报错,抛出了异常

Caused by: com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.60, class org.springframework.web.multipart.MultipartFileResource, fieldName : resource
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:525)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:160)
	at com.alibaba.fastjson.serializer.FieldSerializer.writeValue(FieldSerializer.java:325)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:456)
	... 110 common frames omitted
Caused by: java.io.FileNotFoundException: MultipartFile resource [photo] cannot be resolved to absolute file path
	at org.springframework.core.io.AbstractResource.getFile(AbstractResource.java:124)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.alibaba.fastjson.util.FieldInfo.get(FieldInfo.java:491)
	at com.alibaba.fastjson.serializer.FieldSerializer.getPropertyValueDirect(FieldSerializer.java:150)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:293)
	... 113 common frames omitted

一个是

Caused by: com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.60, class org.springframework.web.multipart.MultipartFileResource, fieldName : resource

另一个是

Caused by: java.io.FileNotFoundException: MultipartFile resource [photo] cannot be resolved to absolute file path

意思是json工具序列化失败了,然后和MultipartFile有关,

我在网上找了一下相关问题,发现了这个 https://github.com/alibaba/fastjson/issues/3505

1、fastjson在打印JSON字符串时,会通过反射得到一个object的所有getter方法,然后取其值,最后拼装成一个JSON字符串。

2、MultipartFile对象有一个 Resource getResource() 方法

3、fastjson在得到Resource后,会继续对Resource对象进行遍历

4、Resource是一个接口,其中有个 getFile 方法,MultipartFileResource本身并没有对 getFile 进行重写

那是什么东西触发了fastjson去序列化MultipartFile呢?是日志框架syslog

解决

既然MultipartFile会被强行序列化,那我们只要设置MultipartFile跳过序列化就行了,这里我们可以用 @JSONField(serialize = false) 修饰

但是直接用来修饰参数不会生效,所以需要给MultipartFile封装一层

public class MyFile {
    @JSONField(serialize = false)
    private MultipartFile file;

    public MultipartFile getFile() {
        return file;
    }

    public void setFile(MultipartFile file) {
        this.file = file;
    }
}
	 @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	 public Map<String, String> uploadPhoto(MyFile file, HttpServletRequest request) throws IOException, ServletException {
	 	 Map<String, String> ret = new HashMap<String, String>();
		 logger.info("getName = "+file.getFile().getName());
		 logger.info("getOriginalFilename = "+file.getFile().getOriginalFilename());
		 ret.put("type", "success");
		 return ret;
	 }
 

--------------------------------------------------------------------------分割线---------------------------------------------------------------------------------------

关于在js中获取<input type="file">的值

<input type="file">

中是不能使用v-model双向绑定的,所以想在js中获取该input的值,需要操作操作DOM

在JavaScript中需要通过document.querySelector("#demo")来获取dom节点,然后再获取这个节点的值。在Vue中,我们不用获取dom节点,元素绑定ref之后,直接通过this.$refs即可调用,这样可以减少获取dom节点的消耗。

摘自:Vue中ref和$refs的介绍及使用_越努力,越幸运!-CSDN博客

例如:

<input type="file" ref="picture" accept="image/*">

在 vue.js 中

      var inputDOM = this.$refs.picture;
      var file = inputDOM.files;
      console.log(file[0]);  //文件内容

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值