【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(fil
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节点的消耗。
例如:
<input type="file" ref="picture" accept="image/*">
在 vue.js 中
var inputDOM = this.$refs.picture;
var file = inputDOM.files;
console.log(file[0]); //文件内容
更多推荐
所有评论(0)