首页 > 其他分享 >发送 POST 请求时常见 Content-Type 的设置以及参数传递

发送 POST 请求时常见 Content-Type 的设置以及参数传递

时间:2024-01-26 10:33:41浏览次数:24  
标签:http 请求 form Content const POST Type

0. 前置须知

1. 你需要知道

  1. 此文是归来仍是制杖专用笔记,主打我88岁也能看懂;
  2. 此文只考虑请求,且 get 请求因语义,一般没有请求体,故不需要指定 Content-Type
  3. 对于请求,Content-Type 的作用是:告诉服务端我携带的 请求体容器 是什么格式;
  4. 对于响应,Content-Type 的作用是:告诉浏览器按什么格式解析,如返回一个静态页面,服务端需要指定 媒体类型为 text/html,如果指定 text/plain 则会错误的按照文本格式,渲染成文档标签;
  5. Content-Type: media type,charest,boundary;即:媒体类型,字符编码,边界;
  6. 此文只关注 post 请求的三个媒体类型,即:
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. application/json
  7. 标头 Content-Length: number 注明请求体长度;
  8. 关于 HTML 的 charset:
    其实是编码而不是字符集,说明如何把实体内容的二进制码转换为特定字母表即对应字符集中的字符。
    如:charset=UTF-8,请求时是告诉应该按照 UTF-8 编码方式编码,在响应里是告诉浏览器要按照 UTF-8 编码方式解码,即把 二进制码 ==> Unicode字符集中的字符。

2. 备注

关于第3点的示例,参考链接

1. 指定媒体类型为 text/html

2. 指定媒体类型为 text/plain

1. application/x-www-form-urlencoded

application/x-www-form-urlencoded 为 http 请求默认;
请求体在 Form Data 中;
数据被编码成键值对,如 username=admin&id=1

1. 表单构建

原生 form 表单,请求头的 Content-Type<form> 元素上的 enctype 属性指定;
不指定默认为 application/x-www-form-urlencoded
不需要文件上传时才使用这种媒体类型,因为使用此种媒体类型,文件也会被编码为 key-value 的形式,多个 key-value 之间用&分隔(注意 value 为 String),如: username=admin&id=1&file=test.png

<form action="http://127.0.0.1:8888/formdata" method="post">
  <input type="text" name="username" />
  <input type="text" name="id" />
  <input type="file" name="file" class="file" />
  <input type="submit" />
</form>


2. 手动构建,直接拼接

不想写form表单的情况~但模拟

<input type="text" name="username" id="username" />
<input type="text" name="id" id="id" />
<button class="submit">提交</button>

<script>
  const btn = document.querySelector('.submit');
  btn.addEventListener('click', () => {
	const username = document.getElementById('username').value;
	const id = document.getElementById('id').value;
	const http = new XMLHttpRequest();
	http.open('post', 'http://localhost:8888/formdata');
	http.setRequestHeader(
	  'Content-Type',
	  'application/x-www-form-urlencoded'
	);
	// 手动拼接!!!
	http.send(`username=${username}&id=${id}&obj=${JSON.stringify({ name: '1' })}`);
	http.onreadystatechange = () => {
	  if (http.readyState === 4 && http.status === 200) {
		console.log('数据返回成功!');
	  }
	};
  });
</script>


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

// 错误写法:
http.send(`username=${username}&id=${id}&obj=${{ name: '1' }}`);

错误写法:

2. multipart/form-data

Multipart 消息结构允许客户端在一次 HTTP 请求中发送多个部分数据,每部分数据用 boundary 分隔,且 Content-Type 可以不同。Multipart 并不是一种专一的数据类型,它有很多子类型,例如:multipart/mixed,multipart/form-data 等。Multipart 是一种常见的数据格式,常用于上传文件和发送包含多种数据类型的单个请求。正确地使用 Multipart 可以方便地实现多种数据的传输,提高数据传输效率和用户的使用体验,减少服务器的请求次数。
传输内容某部分数据可以有二进制类型,如:图片、mp3、文件;
请求体在 Form Data 中;
原生 form 指定 encType 为 'multipart/form-data',浏览器会自动生成一个 boundary,用于分割报文的请求头和请求体以及请求头内容各字段;
文件上传,File 对象通常来自于用户在 <input>元素上选择文件后返回的 FileList 对象!!!对象!对象!;
JS 中,<input class="file"/>选择文件后,FileList 对象可通过document.querySelector('#file').files 获取到,多选文件时,多个文件的属性名为 index;

0. 备注

关于第四点的多选的情况:

1. 表单构建

<form
  action="http://127.0.0.1:8888/formdata"
  method="post"
  enctype="multipart/form-data"
>
  <input type="text" name="username" id="username" />
  <input type="text" name="id" id="id" />
  <input type="file" name="file" class="file" />
  <input type="submit" />
</form>




2. 手动构建,涉及formData对象的使用

观察原生表单发请求的Content-Type,发现后面还有个自动生成的 boundary !
在发送请求时将请求头中 Content-Type 属性给写死为 multipart/form-data,浏览器无法自动给我们的报文添加 boundary,后端接收后,无法识别传递来的文件中的boundary,从而无法区分一个文件的内容从报文的哪个地方开始,又从报文的哪个地方结束,最终导致文件上传失败;
虽然我们需要 Content-Typemultipart/form-data,但是发送请求时不设置,浏览器识别参数类型为 formData,会自动添加!

这里只考虑了原生如何写,axios可参考,咱暂时没遇到过这种需求捏

<input type="text" name="username" id="username" /> 
<input type="text" name="id" id="id" />
<input type="file" name="file" class="file" />
<button class="submit">上传</button>

<script>
  const btn = document.querySelector('.submit');
  const formData = new FormData();
  btn.addEventListener('click', () => {
	const files = document.querySelector('.file');
	const username = document.getElementById('username').value;
	const id = document.getElementById('id').value;
	formData.append('username', username);
	formData.append('id', id);
	formData.append('file', files.files[0], files.files[0].name);
	// 注意:formData 打印为空,可通过此种方式查看~
	for (let val of formData.values()) {
	  console.log(val);
	}
	const http = new XMLHttpRequest();
	http.open('post', 'http://localhost:8888/formdata');
	// 不设置 content-type!!!
	// http.setRequestHeader('Content-Type', 'multipart/form-data');
	http.send(formData);
	http.onreadystatechange = () => {
	  if (http.readyState === 4 && http.status === 200) {
		console.log('数据返回成功!');
	  }
	};
  });
</script>

注意: formData.append(name,value[,filename)

  • 第一个参数对应表单的 name,即后端需要接收的参数名;
  • 第二个参数对应为表单值,即接收的value;
  • 第三个参数在第二个参数值为 blob 类型时,可选,为文件名。

3. application/json

请求体在 Request Payload 中;
数据为 JSON 字符串,原生 ajax 需手动序列化,axios 不需要~

<button class="submit">提交</button>
<script>
  const btn = document.querySelector('.submit');
  btn.addEventListener('click', () => {
	const params = {
	  name: 'ouo',
	  age: 18,
	};
	const http = new XMLHttpRequest();
	http.open('post', 'http://localhost:8888/json');
	http.send(JSON.stringify(params));
	http.setRequestHeader('Content-Type', 'application/json');
	http.onreadystatechange = () => {
	  if (http.readyState === 4 && http.status === 200) {
		console.log('数据返回成功!');
	  }
	};
  });
</script>

标签:http,请求,form,Content,const,POST,Type
From: https://www.cnblogs.com/pupyy/p/17954809

相关文章

  • 使用命令行方式搭建uni-app + Vue3 + Typescript + Pinia + Vite + Tailwind CSS + uv
    使用命令行方式搭建uni-app+Vue3+Typescript+Pinia+Vite+TailwindCSS+uv-ui开发脚手架项目代码以上传至码云,项目地址:gitee.com/breezefaith…目录一、前言近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台......
  • get 和post的异同
      GET和POST的区别 对比GET与POST。1.前言最近看了一些同学的面经,发现无论什么技术岗位,还是会问到get和post的区别,而搜索出来的答案并不能让我们装得一手好逼,那就让我们从HTTP报文的角度来撸一波,从而搞明白他们的区别。2.标准答案在开撸之前吗,让我们先看一下......
  • 5-The Untyped Lambda Calculus
    引入在lambda演算中,所有事物都是函数lambda演算式中有三种项:变量x,形如x变量x在另外一个项t1中的抽象abstraction,形如λx.t1将项t1作用于t2,形如t1t2有如下的简单的递归定义来总结上述三种项的形式:t::=x(variable)λx.t(abstrac......
  • Jenkins持续集成+Apipost配置方法
    Jenkins配置Apipostcli基于Nodejs运行需要在jenkins上配置NodeJs依赖Step1:在插件管理中安装NodeJs在全局工具中配置NodeJs和包名apipost-cli配置到Jenkins我们可以将创建好的CLI脚本部署到Jenkins中去持续集成进行测试。Step1:新建一个任务Apipost-test点击新建任务,输入任务名称,......
  • [原创]Windows安装配置PostgreSql_15.5.1数据库
    [原创]Windows安装配置PostgreSql_15.5.1数据库   PostgreSql数据库有多种安装方式,windows上常用的是installer方式、binary手动安装方式,本文采用手动安装的方式处理。总体过程比较简单,有mysql配置经验的分分钟的事儿。    一、下载并解压文件到具体安装目录。 ......
  • Jenkins持续集成+Apipost配置方法
    Jenkins配置Apipostcli基于Nodejs运行需要在jenkins上配置NodeJs依赖Step1:在插件管理中安装NodeJs  在全局工具中配置NodeJs和包名apipost-cli 配置到Jenkins我们可以将创建好的CLI脚本部署到Jenkins中去持续集成进行测试。Step1:新建一个任务Apipost-test点击......
  • Flask : GET-POST
    fromflaskimportFlask,request,jsonifyfromflask_restfulimportApi,Resource,reqparseapp=Flask(__name__)api=Api(app)####--GET请求参数--传递参数到GET请求中#####1.GET传递查询字符串参数#URL进行GET请求:http://localhost:5000/users?......
  • 无法加载响应数据:request content was evicted from inspector cache
    这个错误通常是由于请求返回的内容太大而导致的。浏览器的开发者工具(Inspector)有一个缓存限制,如果请求的内容超过了这个限制,就会出现这个错误。解决这个问题的方法有几种:减小请求的内容大小:可以通过压缩请求的内容或者减少不必要的数据来减小请求的大小。增加缓存限制:可以......
  • java aspect 切面怎么获取 POST 数据
    javaaspect切面怎么获取POST数据/***切面*/@Aspect@ComponentpublicclassPostRequestBodyAspect{@Pointcut("execution(*com.example.controller.*.*(..))")publicvoidcontrollerMethods(){}......
  • OpenHarmony—TypeScript到ArkTS约束说明
    对象的属性名必须是合法的标识符规则:arkts-identifiers-as-prop-names级别:错误在ArkTS中,对象的属性名不能为数字或字符串。通过属性名访问类的属性,通过数值索引访问数组元素。TypeScriptvarx={'name':'x',2:'3'};console.log(x['name']);console.log(x[2]);ArkT......