背景
最近在开发一个功能时,涉及到向后端接口发送:
- JSON请求参数
- 多个文件
刚开始想通过RequestBody(application/json)形式进行传值,但是文件不好处理。有一个通过application/json传输文件数据的方法,就是将文件转成base64,然后在后端进行处理。但是这种方式涉及到大文件传输的时候,转成base64会消耗过多成本
于是找来找去找到按form表单的形式提交请求参数(按理来说本该如此),但是如何传输json数据倒变成了一个问题,直到找到这么一个文档,参考之后解决了目前的问题。
https://springdoc.cn/spring-file-upload-json/
解决历程
- 后端接口:
@PostMapping("/creation")public void testFormData(@RequestPart("files") MultipartFile[] files,@RequestPart("dto") Dto dto) {System.out.println("hello a shuge");String jsonStr = JSONUtil.toJsonStr(dto);System.out.println(jsonStr);for (MultipartFile file : files) {System.out.println(file.getOriginalFilename());System.out.println(file.getName());}}
注意到,上面testFormData方法中的请求参数 使用的注解 是:@RequestPart
- 前端请求
function handleFileUpload(event) {
// 在这里构造上传要用的fileListconst files = event.target.files;if (files) {for (let i = 0; i < files.length; i++) {if (fileList.length < 20 && files[i].type.includes('image')) {fileList.push(URL.createObjectURL(files[i]));}}}
}
let formData = new FormData();let request = {}; // json数据
// fileList是上面方法中fileList.push(URL.createObjectURL(files[i]));添加的元素for (let key in fileList) {formData.append('files', new Blob(fileList), 'files'); // 往formData中添加blob数据,这里涉及到append另外一个用法}// 注意下面:设置json数据时候,第三个参数指定此时set的数据是application/json类型formData.set('dto', new Blob([JSON.stringify(request)], { type: 'application/json' }));// 遍历formData,打印到consolefor (var pair of formData.entries()) {console.log(pair[0] + ', ' + pair[1]);}UploaderApi.publishProduct(formData).then((res) => {if (res.success) {console.log("success");} else {console.log("failed");}}).catch((err) => {console.log("error");});
http.interceptors.request.use((config) => {// 在发送请求之前做些什么if (config.method === 'post') {// 这里处理上传文件的请求if (config.headers['Content-Type'] === 'multipart/form-data') {const formData = new FormData();// 构造新的formData(如果不需要添加reqId/stamp)那这步就可以省略了,直接config.data=formData就行for (var pair of config.data.entries()) {formData.append(pair[0], pair[1]);}formData.append('requestId', reqId);formData.append('stamp', RequestUtil.generateTimestamp());config.data = formData;} else {config.headers['Content-Type'] = 'application/json;charset=utf-8';config.data = {...config.data,requestId: reqId,stamp: RequestUtil.generateTimestamp(),};}}return config;},(error) => {// 对请求错误做些什么return Promise.reject(error);},
);
请求参数实例
以上,就可以通过axios请求后端接口传输 json字符串+多文件
注意
涉及到的内容
- SpringBoot中@RequestPart的用法
- 前端FomrData.append与set的区别
- 通过将requestBody以contentType=application/json形式写入formData中(里面其实是blob类型数据)