起因
最近在实习的时候主要去做前后端的对接,有一说一,是有点烦的,因为有些参数带我的老师也忘记是做什么的了,所以还是蛮费力的。刚好遇到了一个上传文件并且涉及多个表的级联修改,所以一同发送的对象的属性也很多,前端传到后端时接收到的参数都是null,解决办法如下。
解决
//前端
let formdata = new FormData();
formData.append("file",File);
let params = {
"param1":value1,
"param2":value2,
...
"paramn-1":valuea,
"paramn":valueb,
};
formData.append('data', new Blob([JSON.stringfy(params)],{type: "application/json"}));
axios.post(url,formdata).then(res=>{
console.log(res);
})
复制代码
//后端
@PostMapping("/file")
@ResponseBody
public void fileReceive(
@RequestPart("params") Params params,
@RequestPart("file") MultipartFile file) {
System.out.println("params"+params);
System.out.println("file"+file);
}
复制代码
原因
前端上传方式选择
一般情况下文件的上传是由前端发送formdata来实现的,当然也有使用base64编码来向后端传参的,这里我们选择了formdata进行传参。主要是由于《RFC 1867: Form-based File Upload in HTML》 文档在简介中说明文件上传作为一种常见的需求,在目前(1995年)的html中的form表单格式中还不支持,因此提出了一种兼容此需求的mime type,即multipart/form-data
。
文档中也写了为什么要新增一个类型,而不使用旧有的application/x-www-form-urlencoded
:因为此类型不适合用于传输大型二进制数据或者包含非ASCII字符的数据。平常我们使用这个类型都是把表单数据使用url编码后传送给后端,二进制文件当然没办法一起编码进去了。所以multipart/form-data
就诞生了,专门用于有效的传输文件。
后端接收方式选择
本人使用的后端框架为springboot,通常情况下controller里使用@RequestBody
来接收JSON等类型的数据或是使用@RequestParam
来接收application/x-www-form-urlencoded
和multipart/form-data
。由于我们在formdata中传输的对象属性较多,不可能一个个的使用@RequestParam
来接收,这样看起来十分冗长并且不宜于维护。
故此我们使用@RequestPart
来接收对象,它支持formdata和MultipartFile类型,并且当请求为multipart/form-data
时,@RequestParam
只能接收String类型的name-value值,而@RequestPart
可以接收复杂的请求域(像json、xml)故此选择此注解。你也可以在SpringFramework文档中查找@RequestPart
注解来获得更详细的内容。
前端上传为何使用BLOB对象
这是由于@RequestPart
注解在请求为multipart/form-data
的对象中解析JSON时,若未声明类型为Content-Type: application/json
的话是无法正常序列化对象的。