背景

随时随地给大家提供技术支持的葡萄又来了。这次的事情是这样的,提供demo属于是常规操作,但是前两天客户突然反馈压缩传输模块抛出异常,具体情况是压缩内容传输到服务端后无法解压。

由于代码没有发生任何变动,前端相关依赖也没有升级,服务端java版本也没有变化,所以我们可以推定为环境问题;进一步仔细检查,经过反复对比后突然发现服务端收到的压缩内容变长了;和前端请求内容进行对比,发现所有的\r和\n都变成了\r\n。

综合以上分析我们初步判断:问题出在了浏览器转译之中。为了验证猜想是否正确,葡萄将chrome版本回退到92版,异常消失,服务端接收的内容也没有被替换。

问题是顺利解决了,但是Chrome POST数据内容居然会在传输过程中发生变化。一直擅长大前端技术的葡萄绝不认输,为了弄明白这一原因,我们来看看POST的细节操作到底有什么。

控制字符

首先我们需要搞清楚几个控制字符的含义。

  • 回车符(CR)和换行符(LF)是文本文件用于标记换行的控制字符(control characters)或字节码(bytecode)。
  • CR = Carriage Return,回车符号(\r,十六进制 ascii 码为0x0D,十进制 ascii 码为13),用于将鼠标移动到行首,并不前进至下一行。
  • LF = Line Feed,换行符号( \n, 十六进制 ascii 码为 0x0A,十进制 ascii 码为10)。

    紧邻的 CR 和 LF(组成 CRLF,\r\n,或十六进制 0x0D0A)将鼠标移动到下一行行首。(Windows 操作系统默认的文本换行符为 CRLF;Linux 以及 macOS 系统默认使用 LF,早期的 mac os 系统使用 CR 换行。)

在代码管理中,在不同操作系统下CRLF会有很大不同。下面在不同系统中为大家实际演示一下:

在Mac Visual Code中新建一个文档默认为LF,而Windows中为CRLF,可以选择切换行尾序列的内容的类型。



Mac版Visual Code



Windows 版

面对这种情况,需要开发者统一CRLF,以免不同操作系统开发导致代码管理的混乱。

POST传输的数据变化

弄明白了在不同系统中,控制字符会出现不同的原因,接下来我们就需要搞清楚为什么POST的数据在传输过程中发生了变化。

我们来写个简单Demo测试一下。先在页面上放一个允许换行的textarea, 输入带换行的文本,获取内容看到只有\n转译。通过FormData直接post数据到服务端,然后直接返回,看到\n全部变成了\r\n。

            var uploadData = document.getElementById("ta").value
var formData = new FormData();
formData.append("data", uploadData)
fetch("http://localhost:8088/spread/getpdf", {
body: formData,
method: "POST"
}).then(resp => resp.text())
.then(text => {
console.log(JSON.stringify(text));
document.getElementById("result").innerHTML= JSON.stringify(text)
})

浏览器标识:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36

回退Chrome到92版本,发送和接收文本此时编为一致:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36

深入探究这一原因,我们了解到互联网请求意见稿2046(RFC 2046)4.1.1.中有明确说明:

 “ The canonical form of any MIME‘text’ subtype MUST always represent a
line break as a CRLF sequence. “

这里我们可以看到所有的文本类型都要使用CRLF,而Chrome只是修复了一个“bug”,对于用户而言,在普通文本中用户感知不到CR、LF和CRLF的区别,但是当使用场景转换到解压的文本内容就变得十分重要。

三种解决方式

大家都知道POST是HTTP的一个常用方法,而另一个我们常用的方法是GET。

关于GET和POST区别以及使用相关问题这里不做赘述,要解决POTS传输的数据变化问题,最相关的是Content-Type。

首先我们来了解Content-Type和MIME分别是什么:

Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些Asp网页点击的结果却是下载到的一个文件或一张图片的原因。

在POST中常用的Content-Type有application/x-www-form-urlencoded、multipart/form-data和application/json。

1、 application/x-www-form-urlencoded

将需要内容提交表单后,内容会按照name1=value1&name2=value2的方式编码,并且key和valu e都会进行URL转码。

对于"\n"和"\r" 会被转码为'%0A'和'%0D',通过这种传输方式,避免了浏览器的对CRLF的修正可以解决以上问题。

但是这样转码会增加文本长度,原本1个字符变成了3个,结果是压缩的文本又变长了。

2、multipart/form-data

当需要想服务器提交文件时,就需要使用这种方式。前面代码中我们可以看到当formData是普通文本是会被修正,为了解决这个情况我们可以将string内容封装到Blob中作为文件流传输,来避免修正。

这样传输,服务端会以文件方式收到内容,直接读取Stream内容;对于压缩文本,这种处理方式最优。

           var formData = new FormData();
formData.append("data", uploadData)
formData.append("data1", new Blob( [uploadData]))

上图展示了同样的内容,使用不同方式进行传输。

3、 application/json

Json也是目前比较流行的传输方式,json的内容在post传输中也不会被改变,如果文本内容不长,也是不错的方式。

          fetch("http://localhost.charlesproxy.com:8088/spread/postjson", {
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({data: uploadData}),
method: "POST"
}).then(resp => resp.text())
.then(text => {
console.log(JSON.stringify(text));
document.getElementById("result").innerHTML= JSON.stringify(text)
})

总结

作为一个前端er,除了HTML、CSS和Javascript三大件,熟练使用Axios等类库调用API,更不可忽视的是要了解如何调试网络请求,在项目出现问题时能快速定位到问题的所在。

这里提供了在 Angular 框架下动态加载js文件时返回 Content-Type 为text/html 的Demo,大家感兴趣的可以自行下载试试。

Demo 地址: https://gcdn.grapecity.com.cn/forum.php?mod=attachment&aid=NDc5OTJ8YmU1Mjk0NDN8MTY1MDI2MTI0M3wxfDUwOTgw

数据传输POST心法分享,做前端的你还解决不了这个bug?的更多相关文章

  1. 做前端的你还没用这些软件?? out 啦

    1. 编辑器 写代码只是生产软件过程中的一环.无论是数据结构.编译原理.操作系统还是组成原理都是编码的重要基础,试问没有学过编译原理的人能够针对性地进行编译优化吗?不懂操作系统的人能玩得转linux吗 ...

  2. 绝对精品推荐做前端的看下:Web前端开发体会十日谈

    20151208感悟: 前端人的角度来看的话,感觉像是阅读一个大牛前端的全部武功的一个秘籍说明,里面的思想高价值蛋白真是太多太多,推荐看. Web前端开发体会十日谈 一直想写这篇“十日谈”,聊聊我对W ...

  3. zend studio 做前端推荐安装的插件

    zend studio 做前端推荐安装的插件 1.Aptana插件代码提示 Zend Studio的aptana插件,解决了Zend Studio对前台代码支持不足的问题,而且在某些方面还比诸如dw优 ...

  4. 为什么做前端要做好SEO

    我就挑干货说啦SEO可能听起来很高大上,其实翻译成中文就是"搜索引擎优化",它只是通过一定的方法在网站内外发布文章.交换连接等,最终达到某个关键词在搜索引擎上获得好的排名. 我有幸 ...

  5. 一个JS效果竟然要研究一天,我是不是不适合做前端?

    前言 今天这篇文章的标题,显然是要搞事情.一个JS交互效果,居然花费了一天的宝贵时间才研究出来,我是不是不太适合做前端? 别急,搬好小板凳,正文从这开始- 本来今天下班回来感觉有点累,想着今天就别学了 ...

  6. 12个实用的 JavaScript 框架分享给前端开发者

    JavaScript库是预先编写的 JavaScript 工具代码,让开发者可以更容易开发 JavaScript 应用.这个列表我们列出了2017年1月份功能丰富的 JavaScript 库,可以帮助 ...

  7. 做前端好还是Java好?

    做前端好还是Java好?看这三方面 转载 2017年11月14日 00:00:00 1047这几年来伴随着互联网的迅速发展,新兴互联网产业的兴起,传统行业也逐渐开始互联网化,使得互联网职业在这样的背景 ...

  8. 从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js

    从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js /************************************************************* ...

  9. php是做前端的吗?

    php是做前端的吗 不是,php是后台脚本语言,由服务器执行. PHP即“超文本预处理器”,是一种通用开源脚本语言.PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言.PHP独特的语 ...

随机推荐

  1. Windows 8下完美使用Virtual PC 2007(virtual pc 2007 64 win8 兼容性)

    Windows 8下完美使用Virtual PC 2007(virtual pc 2007 64 win8 兼容性) 一.从微软的官方网站下载Virtual PC 2007 SP1英文版,文件名为se ...

  2. 10年.NET老程序员推荐的7个开发类工具

    做.NET软件工作已经10年了,从程序员做 到高级程序员,再到技术主管,技术总监.见证了Visual Studio .NET 2003,Visul Studio 2005, Visual Studio ...

  3. 实习项目1-串口IP升级调试

    设计目标:设计一个串口IP,要求1:输入时钟频率任意,如0-400M时钟频率:要求2:波特率超过常见的115200,要求达到4M. 设计核心思路:波特率计算公式,divp10x = (10 * fsy ...

  4. Spring Data Jpa 更新操作

    第一步,通过Repository对象把实体根据ID查询出来 第二部,往查出来的实体对象进行set各个字段 第三步,通过Repository接口的save方法进行保存 保存和更新方式(已知两种) 第一种 ...

  5. 什么是 Spring Profiles?

    Spring Profiles 允许用户根据配置文件(dev,test,prod 等)来注册 bean.因此,当应用程序在开发中运行时,只有某些 bean 可以加载,而在 PRODUCTION中,某些 ...

  6. 什么是springboot?为什么要用springboot?

    一.什么是springboot? Springboot是spring发展到一定程度的产物,但并不是spring的替代品,springboot是为了让程序员更好的使用spring.Spring随着发展逐 ...

  7. pip 安装更新卸载 pip/yum换源

    pip安装:sudo apt-get install python3-pip pip更新:sudo pip3 install --upgrade pip pip卸载:sudo apt-get remo ...

  8. 一个 Spring 的应用看起来象什么?

    一个定义了一些功能的接口.这实现包括属性,它的 Setter , getter 方法和函数等.Spring AOP.Spring 的 XML 配置文件.使用以上功能的客户端程序.

  9. BootstrapBlazor 智能生成神器(一)AutoGenerateColumnAttribute 特性介绍

    原文连接:https://www.cnblogs.com/ysmc/p/16074645.html BootstrapBlazor 官网地址:https://www.blazor.zone 介绍 Bo ...

  10. Python - 异常处理初步