起因
今天下午下班前,后端的小伙伴突然问了我一个问题,“前端POST的FormData能不能设置Content-Type”。
嘿,当然能啊,不就是请求头的Content-Type吗?
乌龙后才发现,他问我的是,能不能给FormData的单个字段设置Content-Type,我当时就懵逼了,额,好像,不行吧。
调研过程
这激起了我的斗志,因为他说,PostMan可以设置单个字段的Content-Type,我盯着看了一下,确实可以,想看下控制台,结果这兄弟用的是客户端,懒得抓包,就回去自己折腾去了。
我们知道,newFormData的实例,对于字段设置有两个方法,append与set,二者的区别是:
append是追加字段,而set是添加或替换,即set的时候,该字段如果已经存在,则更新当前字段。
letform_data=newFormData()form_data.append(a,1)form_data.append(a,2)form_data.set(b,3)form_data.set(b,4)fetch(/test,{method:POST,body:form_data,})
抓包看效果即可
我确定就这个两个api可以给FormData添加字段,很自觉地去复习MDN文档。
文档说得很清楚,append与set在传参方面一样,都是三个,文件的name,就是常说的key,value就是值或者文件/图片啥的,最后一个是显式的告诉后端我们的文件名,常见伪代码如下:
form_data.set(file,file[,filename])
很明显嘛,没有对这个name的值value设置Content-Type的地方。
就在我准备明确告知不行的时候,多年的踩坑经验告诉我,事情没那么简单……
抱着稳妥方案,Google了一下,果然找到了相关的问题:
当我看到这个答复的时候,一巴掌抽到自己嘴丫上,怎么就没想到呢,使用BloB构建一个类文件对象不就完了!挺萌的,File不就是继承自Blob的嘛。
HTML
buttononclick="clickSubmit()"submit/button
JS
functionclickSubmit(){letform_data=newFormData()form_data.append(json_key,newBlob([JSON.stringify({a:1,b:2})],{type:application/json}))alert(form_data.get(json_key).type)fetch(/test_post,{method:post,body:form_data}).catch(error={console.log(error)})}
嘿,这不就好了?
有啥用
讲道理,我是没遇到过,一般来说,这种FormData上传文件带其他字段,都是直接JSON.stringify处理后的字符串上传的。
不过小伙伴说的场景是,如果支持具体的字段的话,就可以在API文档上体现出更可读的数据结构表达,想想,有道理。
总结
个人认为这个知识点不难,但是挺偏的……作为知识储备还是很好的,如果有兴趣,更可以深入地挖掘下Blob,毕竟图片处理的时候,这个还是很常用的东西~