1. 首页
  2. >
  3. 技术代码
  4. >
  5. 前端技术

FormData字段指定Content-Type

FormData字段指定Content-Type

后面效果需要查看调试器的 Network。

起因

今天下午下班前,后端的小伙伴突然问了我一个问题,“前端 POST 的 FormData 能不能设置 Content-Type”。

嘿,当然能啊,不就是请求头的 Content-Type 吗?

乌龙后才发现,他问我的是,能不能给 FormData 的单个字段设置 Content-Type,我当时就懵逼了,额,好像,不行吧。

调研过程

这激起了我的斗志,因为他说,PostMan 可以设置单个字段的 Content-Type,我盯着看了一下,确实可以,想看下控制台,结果这兄弟用的是客户端,懒得抓包,就回去自己折腾去了。

我们知道,new FormData 的实例,对于字段设置有两个方法,append 与 set,二者的区别是:

append是追加字段,而 set 是添加或替换,即 set 的时候,该字段如果已经存在,则更新当前字段。

let form_data = new FormData() 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, }) 

抓包看效果即可

FormData字段指定Content-Type

我确定就这个两个 api 可以给 FormData 添加字段,很自觉地去复习 MDN 文档。

FormData字段指定Content-Type

文档说得很清楚,append 与 set 在传参方面一样,都是三个,文件的 name,就是常说的 key,value 就是值或者文件/图片啥的,最后一个是显式的告诉后端我们的文件名,常见伪代码如下:

form_data.set('file', file[, 'filename'])

很明显嘛,没有对这个 name 的值 value 设置 Content-Type 的地方。

就在我准备明确告知不行的时候,多年的踩坑经验告诉我,事情没那么简单……

抱着稳妥方案,Google 了一下,果然找到了相关的问题:

FormData字段指定Content-Type

FormData字段指定Content-Type

当我看到这个答复的时候,一巴掌抽到自己嘴丫上,怎么就没想到呢,使用 BloB 构建一个类文件对象不就完了!挺萌的,File 不就是继承自 Blob 的嘛。

HTML

<button onclick="clickSubmit()">submit</button>

FormData字段指定Content-Type

JS

function clickSubmit() {   let form_data = new FormData()   form_data.append('json_key', new Blob([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字段指定Content-Type

嘿,这不就好了?

有啥用

讲道理,我是没遇到过,一般来说,这种 FormData 上传文件带其他字段,都是直接 JSON.stringify 处理后的字符串上传的。

不过小伙伴说的场景是,如果支持具体的字段的话,就可以在 API 文档上体现出更可读的数据结构表达,想想,有道理。

总结

个人认为这个知识点不难,但是挺偏的……作为知识储备还是很好的,如果有兴趣,更可以深入地挖掘下 Blob,毕竟图片处理的时候,这个还是很常用的东西~