前提

在前后端联调的时候总会牵扯到一个问题,就是参数的传递方式,GET请求就不说了,参数往url后面一拼,万事大吉。

然而一到POST请求的时候,花样就来了,后端童鞋跟你说,我这个接口在postman试过是没问题的,你content-type设置成我要的就行了,要是真这么简单今天咱也就啥也不写了。

今天就来聊聊设置不同content-type时,前端童鞋的参数设置方式,以及在http中是什么样的,以及后端是怎么接受的。

content-type的值非常非常多,有兴趣的去查一下 HTTP Content-type 对照表,我们今天只谈POST请求 request headers中的content-type

准备工作

前端: fetch; 字符集设置: charset=utf-8

抓包工具: charles; 浏览器: chrome

node服务: Koa; 后端: SpringBoot

简单封装post

export const post = (url: string, params: any, options: any = {}) => {

return fetch(url, {

method: 'post',

headers: {

...options.headers,

},

body: params

});

}

node服务

import router from './router/index'; // 路由配置,无关紧要

const Koa = require('koa');

const koaBody = require('koa-body');

const app = new Koa();

app.use(koaBody({

multipart: true

}));

app.use(async (ctx, next) => {

console.log(ctx.request.headers);

console.log('body', { ...ctx.request.body }); // 主要看一下打印出的body

ctx.params = {

...ctx.request.body,

...ctx.query

};

await next();

});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000)

text/plain

首先就是content-type什么都不设置时,大多数情况下(下面马上就有例外)都会被浏览器默认为 text/plain 将参数设置为纯文本的形式,浏览器也不会对其进行处理。实际中使用时基本也不会这样来用,可跳过

application/json

代码

设置一下Content-type: application/json

post('/api/post-application-json', JSON.stringify({

name: 'application',

content: {

value: 20,

names: ['zhang', 'li']

}

}), {

headers: {

'Content-type': 'application/json; charset=utf-8'

}

});

Chrome

charles

node后端

按照json格式就没啥问题

Jave后端

@Data

private class FormVO {

private Integer id;

private String name;

}

@RequestMapping(value = "/post-application-json", method = RequestMethod.POST)

public int createForm(@RequestBody FormVO form) {

Integer id = form.getId();

String name = form.getName();

return 1;

}

需要为form写定制的class 即FormVO

application/x-www-form-urlencoded

表单上传:数据被编码为名称/值对

传统使用form表单上传时,都会创建一个form

表单构建

action="/api/post-form-urlencoded"

method="post"

encType="application/x-www-form-urlencoded"

>

提交

chrome

charles

可以看出原始文本还是以键值对的形式

问题来了,当你不想写form时,但是后端又要求你用form表单上传时,该怎么构建参数呢

哈哈哈,就手动自己写键值对拼在一起!

手动构建form参数

post('/api/post-form-urlencoded', `id=2&name=wee`, {

headers: {

'Content-type': 'application/x-www-form-urlencoded; charset=utf-8'

}

});

因为键值对的value要求为string,如果有复杂结构,那就需要对复杂value先JSON.stringify一下

post('/api/post-form-urlencoded', `id=2&content=${JSON.stringify({ name: 'aaa' })}`, {

headers: {

'Content-type': 'application/x-www-form-urlencoded; charset=utf-8'

}

});

node后端

JSON.stringify过的字段都得再JSON.parse回来

Java后端

@RequestMapping(value = "/post-form-data", method = RequestMethod.POST)

public Object createForm(@RequestParam Map params) {

Object id = params.get("id");

Object name = params.get("name");

return name;

}

简单愉快,扩展字段也不用手动去写class

multipart/form-data

然后就到了这货了

multipart/form-data: 数据被编码为一条消息,页上的每个控件对应消息中的一个部分

这个也是表单上传,跟application/x-www-form-urlencoded有啥不一样呢,主要是这个更厉害一丢丢,他可以用于上传文件

表单构建

action="/api/post-form-data"

method="post"

encType="multipart/form-data"

>

提交

看起来和application/x-www-form-urlencoded 没啥不一样的

chrome

再看下chrome下,好像也没啥不一样的,除了Content-type

charles

然而再来看看charles下的原始信息

duang! duang! 差别在这呢,被编码成一个消息体了

手动构建form参数采坑

然后就到了踩坑的地方了,不写form表单怎么按这种方式上传呢

首先是参数设置,必须使用FormData来构建参数,别的都白扯,

然后设置Content-type吗,该踩的坑还是踩一下试试

const formData = new FormData();

formData.set('id', '2');

formData.set('name', 'zhang');

post('/api/post-form-data', formData, {

headers: {

'Content-type': 'multipart/form-data; charset=utf-8'

}

});

结果呢,Chrome下

发现跟上面chrome下不太一样, chrome也不给你处理了,服务器也不干了

Error: bad content-type header, no multipart boundary

仔细看看,才会发现原生form, content-type后面还有个boundary,

这玩意干啥的呢

分隔符 上面说过了,form-data会被编码为一条消息,那我怎么分隔开这个消息体,解析得到我想要的键值对呢,就是通过boundary,就是那个特别长的------WebKitFormBoundaryK1IM1NwdabR3WdrA

手动构建form参数正解

所以怎么生成boundary呢,很简单,就不设置content-type,浏览器会因为你的参数是FormData类型,自动为你添加

const formData = new FormData();

formData.set('id', '2');

formData.set('name', 'zhang');

post('/api/post-form-data', formData);

不上截图了,跟form表单一样的东西

node后端

JSON.stringify过的字段都得再JSON.parse回来

form表单的后端处理看起来还是一样的

Java后端

和application/x-www-form-urlencoded 一样

总结

application/json 对于前端来说 真香

form表单对于后端来说,两种无差别,也不需要构造class

以后跟你的后端小伙伴好好商量吧(大哥,用json行不行)

java content-type设置_POST请求时 content-type的设置以及参数传递相关推荐

  1. java content-length_java向服务器post请求时首部字段content-length的计算方法

    当java向服务器post请求时,首部中有一个Content-length字段,即请求主体中的字节数.首部在主体的前面.不过,要写入首部,需要知道主体的长度,而在写首部的时候可能还不知道主体的长度.正 ...

  2. java app token 失效_请求时token过期自动刷新token操作

    1.在开发过程中,我们都会接触到token,token的作用是什么呢?主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的 ...

  3. 微信小程序-当用户拒绝了位置信息的请求时,提醒用户去设置地理位置授权

    如图 当用户点击了取消,拒绝了位置信息的请求.如下图所示,提醒用户去设置地理位置授权,如下图所示, 如果用户没去设置的话,每次只要用户点击进入该页面都会有这个弹窗出现. 相关代码如下所示: wxml: ...

  4. java代码中使用http请求时DnsResolver的问题

    http中使用DnsResolver的方式有两种,一种是使用默认的方式,一种是自定义一个DnsResolver 1. 使用默认的DnsResolver 代码如下: DnsResolver dnsRes ...

  5. input type属性为file时(type=file),上传一次然后做更新input的change事件

    最近在做文件上传,第一次上传之后,再次上传同样的文件,不会做出相应的事件处理: 解决方案: 当你把input的文件取出之后,使用replaceWith覆盖掉以前的input,这样就做到了刷新input ...

  6. css设置竖排字体时letter-spacing无法有效设置字体间距

    因为如果是通过设置宽度来进行自动换行的话,则无法通过letter-spacing或者word-spacing设置字体间距,实际上此时字体间距的本质是行间距,单行只有一个汉字,所以只能通过设置line- ...

  7. axios关于针对请求时长策略设计的思考

    前言 在我们的业务请求中,有很多时候会针对有不同时长的需求策略性设置.这里针对这个需求进行详细的展开. 针对这种情况,我们的timout的一般是根据请求地址来的,所以核心处理技巧便是如何根据不同的re ...

  8. 移动热点服务的属性此计算机,win10移动热点提示:我们无法设置移动热点怎么办_win10显示无法设置移动热点怎么办...

    应该已经有许多用户在使用win10系统的电脑了,在使用过程中难免会遇到一些问题.有的用户可能会遇到在设置移动热点时提示我们无法设置移动热点的情况,这让许多用户感到很烦恼,那么win10移动热点提示:我 ...

  9. 阿里云存储OSS中设置上传文件content type

    阿里云存储OSS中设置上传文件ContentType 如果你使用浏览器上传文件,则浏览器会自动在header中设置正确地content type,然后对文件的访问会得到正确地回应. 如果采用编程的方式 ...

最新文章

  1. 用 GDI 操作 EMF 文件[2]: PlayEnhMetaFile、DeleteEnhMetaFile
  2. Java 9 - 17 特性解读:Java 10
  3. 浅谈wcscpy_s之用法
  4. 【MM模块】 Goods Receipt 收货 3
  5. Python 类常用各种方法及区别
  6. linux系统改ip地址 永久生效,Linux修改IP永久生效
  7. C#中实现QQ截图的功能及相关问题
  8. idea-java项目配置
  9. 2021考研初试成绩多少分过线?
  10. Centos7 PXE服务器部署
  11. 论文丨免费下载SCI全文文献的10个方法
  12. 下跌趋势底背驰的几种经典信号
  13. minus的用法简介
  14. win7系统不能保存文档到服务器,win7 64位系统编辑word文档后无法保存的解决方法...
  15. 阻容感基础02:电阻器原理(1)-电阻器模型
  16. 程序员的你想跳槽了?谨记:哪里都不好混!
  17. 8月第四周回顾:四核产品将发口角先起 AMD遭遇跳票流言
  18. 设平衡二叉排序树(AVL树) 的节点个数为n,则其平均检索长度为log2n
  19. mysql update 多表更新_MySQL UPDATE多表关联更新
  20. 【istioctl】multicluster mesh 管理源码走读

热门文章

  1. 【IOS】 In App Purchase 内置购买 总结
  2. javaWeb实现聊天室(私聊+群聊)
  3. matlab 希腊字母对照表
  4. mac m1 购买并安装正版我的世界 MC
  5. 平台商店虚幻市场正常,epic库无法连接网络,网络端口管理软件导致异常?
  6. 对计算机技术的发展方向研究,现代计算机技术的发展方向趋势
  7. Cisco Packet Tracer官网安装配置
  8. Java 数组定义和访问
  9. JetBrains旗下软件通用激活方法
  10. JS 之 验证电话号码