关于人机交互过程中http通讯及浏览器中的HTML编码、URL编码、base64编码及转义

关于人机交互过程中http通讯及浏览器中的HTML编码、URL编码、base64编码及转义

目录

关于人机交互过程中http通讯及浏览器中的HTML编码、URL编码、base64编码及转义

1、html编码的特殊字符

1.1、HTML 实体

1.2、HTML字符实体,数据的表达

2、URL编码的特殊字符

2.1、URL支持的字符        

2.2、ASCII字符编码表

3、Base64编码的特殊字符

3.1、base64在http和html中有许多使用场景:

3.2、base64字符编码表

3.3、base64字节规则及编码步骤


1、html编码的特殊字符

        HTML encoding character

        HTML 和 XHTML 用标准的 7 比特 ASCII 代码在网络上传输数据。

1.1、HTML 实体

        HTML语言 中的“保留字”,即某些预留字符。
        比如:不能在除“元素”意外的位置,使用小于号(<)和大于号(>),浏览器会误解为它们是标签。
        若有需要让浏览器正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体(character entities)。

1.2、HTML字符实体,数据的表达

1、&号 “加” 特殊字符的“约定实体名称”  “加” ;号,比如符号:   < ,表达为:    &lt;

注意,实体名称:大小写敏感。或者:

2、&号 “加” # “加” 特殊字符的ASCII码  “加” ;号,比如符号:   < ,表达为:    &#60;

        html保留字的字符实体表:

显示结果描述实体名称实体编号
空格&nbsp;&#160;
<小于号&lt;&#60;
>大于号&gt;&#62;
&和号&amp;&#38;
"引号&quot;&#34;
'撇号 &apos; (IE不支持)&#39;
&cent;&#162;
£&pound;&#163;
¥日圆&yen;&#165;
欧元&euro;&#8364;
§小节&sect;&#167;
©版权&copy;&#169;
®注册商标&reg;&#174;
商标&trade;&#8482;
×乘号&times;&#215;
÷除号&divide;&#247;

js中“字面量”字符串转义符:

CodeOutput
\0空字符
\'单引号
\"双引号
\\反斜杠
\n换行
\r回车
\v垂直制表符
\t水平制表符
\b退格
\f换页
\uXXXXunicode 码
\u{X} ... \u{XXXXXX}unicode codepoint Experimental
\xXXLatin-1 字符 (x 小写)

2、URL编码的特殊字符

        Percent-encoding也称URL编码。

        是一种拥有 8 位字符编码的编码机制,这些编码在URL的上下文中具有特定的含义。它有时被称为 URL 编码。编码由英文字母替换组成:“%” 后跟替换字符的 ASCII 的十六进制表示。

        需要编码的特殊字符有:

 ':''/''?''#''['']''@''!''$''&'"'"'('')''*''+'','';''=',        以及,'%' 本身,这一点容易被忽视。

        其他的字符虽然可以进行编码,但是,不需要。

        URL encoding character RFC规范 :

An example HTML documenticon-default.png?t=N7T8https://www.ietf.org/rfc/rfc2396.txt

RFC 3986 - Uniform Resource Identifier (URI): Generic SyntaxUniform Resource Identifier (URI): Generic Syntax (RFC 3986)icon-default.png?t=N7T8https://datatracker.ietf.org/doc/html/rfc3986

https://en.wikipedia.org/wiki/Percent-encodingicon-default.png?t=N7T8https://en.wikipedia.org/wiki/Percent-encoding

2.1、URL支持的字符        

        由于URL只支持英文字母、数字、横杠、下划线、句点、波浪线,若要表示其他字符则需要编码。
        例如:百分号、中文。
        由于百分号也需要编码,因此会出现某些绕过问题。

①、URL编码基于ASCII码:

  • URL中无特殊字符: 全是ASCII可显示字符

https://www.cpuofbs.com/rest/postdata?A=abc&B=123
https://www.cpuofbs.com/rest/postdata?A=abc&B=123

  • URL中包含特殊字符: 空格 、(顿号等等)

https://www.cpuofbs.com/rest/postdata?A= abc&B、=123
https://www.cpuofbs.com/rest/postdata?A=%20abc&B%E3%80%81=123

  • URL中包含特殊字符: 中文

https://www.cpuofbs.com/rest/postdata?学生姓名=英文名abc&身份证号sfzh=432345678909876543
https://www.cpuofbs.com/rest/postdata?%E5%AD%A6%E7%94%9F%E5%A7%93%E5%90%8D=%E8%8B%B1%E6%96%87%E5%90%8Dabc&%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7sfzh=432345678909876543
 


②、特殊字符,先根据当前页面的编码方式转换,比如:

<meta charset="utf-8" content-type="text/html" />,

取其十六进制形式,每两位添加1个%

 2.2、URL编码表

百分比编码后的保留字符
!#$%&'()*+,/:;=?@[]
%20%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D

        在特定上下文中没有保留用途的保留字符也可以进行百分比编码,但在语义上与没有保留的字符没有区别。

        例如,在 URI的“查询”组件(?字符之后的部分)中,/仍被视为保留字符,但它通常没有保留用途,除非特定的 URI 方案另有说明。当字符没有保留用途时,不需要进行百分比编码。

        仅通过保留字符是百分比编码还是按字面显示不同的 URI 通常被认为是不等价的(表示相同的资源),除非可以确定所讨论的保留字符没有保留用途。此确定取决于各个 URI 方案为保留字符建立的规则。

        根据上下文, 空白符 ' ' 将会转换为 '+' (必须在 HTTP 的 POST 方法中使定义 :application/x-www-form-urlencoded 传输方式), 或者将会转换为 '%20' 的 URL。

        以及,'%' 本身,这一点容易被忽视。

2.2、ASCII字符编码表

       HTML 和 XHTML 用标准的 7 比特 ASCII 代码在网络上传输数据。

2.2.1、“32~126”区段,可显式区段:

结果描述实体编号
space&#32;
!exclamation mark&#33;
"quotation mark&#34;
#number sign&#35;
$dollar sign&#36;
%percent sign&#37;
&ampersand&#38;
'apostrophe&#39;
(left parenthesis&#40;
)right parenthesis&#41;
*asterisk&#42;
+plus sign&#43;
,comma&#44;
-hyphen&#45;
.period&#46;
/slash&#47;
0digit 0&#48;
1digit 1&#49;
2digit 2&#50;
3digit 3&#51;
4digit 4&#52;
5digit 5&#53;
6digit 6&#54;
7digit 7&#55;
8digit 8&#56;
9digit 9&#57;
:colon&#58;
;semicolon&#59;
<less-than&#60;
=equals-to&#61;
>greater-than&#62;
?question mark&#63;
@at sign&#64;
Auppercase A&#65;
Buppercase B&#66;
Cuppercase C&#67;
Duppercase D&#68;
Euppercase E&#69;
Fuppercase F&#70;
Guppercase G&#71;
Huppercase H&#72;
Iuppercase I&#73;
Juppercase J&#74;
Kuppercase K&#75;
Luppercase L&#76;
Muppercase M&#77;
Nuppercase N&#78;
Ouppercase O&#79;
Puppercase P&#80;
Quppercase Q&#81;
Ruppercase R&#82;
Suppercase S&#83;
Tuppercase T&#84;
Uuppercase U&#85;
Vuppercase V&#86;
Wuppercase W&#87;
Xuppercase X&#88;
Yuppercase Y&#89;
Zuppercase Z&#90;
[left square bracket&#91;
\backslash&#92;
]right square bracket&#93;
^caret&#94;
_underscore&#95;
`grave accent&#96;
alowercase a&#97;
blowercase b&#98;
clowercase c&#99;
dlowercase d&#100;
elowercase e&#101;
flowercase f&#102;
glowercase g&#103;
hlowercase h&#104;
ilowercase i&#105;
jlowercase j&#106;
klowercase k&#107;
llowercase l&#108;
mlowercase m&#109;
nlowercase n&#110;
olowercase o&#111;
plowercase p&#112;
qlowercase q&#113;
rlowercase r&#114;
slowercase s&#115;
tlowercase t&#116;
ulowercase u&#117;
vlowercase v&#118;
wlowercase w&#119;
xlowercase x&#120;
ylowercase y&#121;
zlowercase z&#122;
{left curly brace&#123;
|vertical bar&#124;
}right curly brace&#125;
~tilde&#126;

2.2.2、“0~30及独立的127”区段,设备控制区段:

       ASCII设备控制代码最初被设计为用来控制诸如打印机和磁带驱动器之类的硬件设备。在HTML文档中这些代码不会起任何作用:

结果描述实体编号
NULnull character&#00;
SOHstart of header&#01;
STXstart of text&#02;
ETXend of text&#03;
EOTend of transmission&#04;
ENQenquiry&#05;
ACKacknowledge&#06;
BELbell (ring)&#07;
BSbackspace&#08;
HThorizontal tab&#09;
LFline feed&#10;
VTvertical tab&#11;
FFform feed&#12;
CRcarriage return&#13;
SOshift out&#14;
SIshift in&#15;
DLEdata link escape&#16;
DC1device control 1&#17;
DC2device control 2&#18;
DC3device control 3&#19;
DC4device control 4&#20;
NAKnegative acknowledge&#21;
SYNsynchronize&#22;
ETBend transmission block&#23;
CANcancel&#24;
EMend of medium&#25;
SUBsubstitute&#26;
ESCescape&#27;
FSfile separator&#28;
GSgroup separator&#29;
RSrecord separator&#30;
USunit separator&#31;
DELdelete (rubout)&#127;

3、Base64编码的特殊字符

        Base64 encoding character

3.1、base64在http和html中有许多使用场景:

1、比如我们在html中表达1个图片文件进行base64编码的src资源,可以:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==

 2、再比如 对文件进行base64编码,我们上传和下载超大文件,可先对其进行base64二进制编码再压缩后,进行,这样可以极大提升效率并提供了“断点”续传的可能

        案例:delphi压缩后使用http协议base64上传下载6G超大文件_pulledup的博客-CSDN博客delphi压缩后使用http协议base64上传下载6G超大文件注:服务端软件,使用高勇出品GYRestServer系列。欢迎使用,加QQ群咨询:174483085一、知识点:1、Delphi自带的压缩解压单元system.zlib.pas中核心函数的使用2、服务端http协议ContentType(mime-type)相关列表类型的注册3、Base64编码的规则4、为何要分块断点续传,并使用TFileStream文件流替代内存流TMemoryStream5、Buffe..icon-default.png?t=N7T8https://blog.csdn.net/pulledup/article/details/121455926

3.2、base64字符编码表

base64_百度百科Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。Base64由于以上优点被广泛应用于计算机的各个领域,然而由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。icon-default.png?t=N7T8https://baike.baidu.com/item/base64/8545775?fr=aladdin

        大写A~Z ,小写a~z , 数字0~9, +  \  ,以及1个特殊的“字符A”结尾标识符 == 

6位二进制补齐后的10进制索引
base64
字符
6位二进制补齐后的10进制索引base64字符6位二进制补齐后的10进制索引base64字符6位二进制补齐后的10进制索引base64字符
0
A
16
Q
32
g
48
w
1
B
17
R
33
h
49
x
2
C
18
S
34
i
50
y
3
D
19
T
35
j
51
z
4
E
20
U
36
k
52
0
5
F
21
V
37
l
53
1
6
G
22
W
38
m
54
2
7
H
23
X
39
n
55
3
8
I
24
Y
40
o
56
4
9
J
25
Z
41
p
57
5
10
K
26
a
42
q
58
6
11
L
27
b
43
r
59
7
12
M
28
c
44
s
60
8
13
N
29
d
45
t
61
9
14
O
30
e
46
u
62
+
15
P
31
f
47
v
63
/

base64字符索引、二进制、base64字符 对照表:

索引2进制Char索引2进制Char索引2进制Char索引2进制Char
0000000A16010000Q32100000g48110000w
1000001B17010001R33100001h49110001x
2000010C18010010S34100010i50110010y
3000011D19010011T35100011j51110011z
4000100E20010100U36100100k521101000
5000101F21010101V37100101l531101011
6000110G22010110W38100110m541101102
7000111H23010111X39100111n551101113
8001000I24011000Y40101000o561110004
9001001J25011001Z41101001p571110015
10001010K26011010a42101010q581110106
11001011L27011011b43101011r591110117
12001100M28011100c44101100s601111008
13001101N29011101d45101101t611111019
14001110O30011110e46101110u62111110+
15001111P31011111f47101111v63111111/

Padding

填充位

=

 代码表示Base64字符表:

Shotgun.Js.Base64 = {
    _table: [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
        'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    ],

3.3、base64字节规则及编码步骤

3.3.1、内存中,字节的编组方式

        通常,计算机的内存中用8位二进制表达1个字符。

        比如10进制数65对应的字符A ,内存中8位表示:0100 0001 :

用24位表示,尾随两个”空字符“NUL (NULL),表示为:

01000001 00000000 00000000

3.3.2、base64的字符内存编组方式

        上述,ASC码表中,每3个字符将被编码为4个字符(3×8 → 4×6);不满4个字符的位,编组完后,以Base64的'='符号做填充:

        3组变4组,将原本3*8=24位,改编为4*6(其中含2位补齐)=24位

        比如上述字符A :0100 0001 :

01000001,从低位开始,6位为1组,尾部补齐:

0001 000000 010000

即:00010000 00010000

查找ASCII编码表10进制结果:16 16

或(标准格式):

00010000 00010000 00000000 00000000

16 16 NUL(null) NUL(null)

        然后,根据该10进制,比照base64字符编码表的索引:

字符A重新编组后:

16 16

对应Base64的Char字符的结果是:

Q Q

或(标准格式):

16 16 NUL(null) NUL(null)  ---------00000000 00000000刚好比对出2个“A”则用==表示:

QQ==

又比如,字符B:0100 0010 :

0100 000000 000000 100000

00010000 00000000 00100000

16                               32

Q                                 g

结果: Qg==

以上为”单字节“,那么如何处理”多字节“,先看案例:

//
window.btoa('B')
'Qg=='
window.btoa('BC')
'QkM='
window.btoa('BCD')
'QkNE'
window.btoa('BCDE')
'QkNERQ=='
window.btoa('BCDEF')
'QkNERUY='
window.btoa('BCDEFG')
'QkNERUZH'
//

规律:1、每3个字节,变成了4个字节;2、重新编组后的字节总数,一定能被4整除,即:4位为1组。

推导:1、只要遇到6位1组的多字节,其按Base64重新编组的结果,就不会产生填充符”=“ ;

3.3.3、js中base64的编码和解码:

// 解决方案 #1 – 在编码之前转义字符串---unescape和escape已弃用  :
function utf8_to_b64(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}; //
function b64_to_utf8(str) {
    return decodeURIComponent(escape(window.atob(str)));
}; //
const bin8 = '01000001', // 00010000 00010000
    bin16 = '0001000000010000', // 00010000 00010000  代表QQ
    bin32 = '00010000000100000000000000000000'; // 00010000 00010000 00000000 00000000  代表QQ==
//
//00010000 00010000
let encodedData = window.btoa("A"); // = Base64编码 (缺陷)
console.log(encodedData); //: QQ==
let decodedData = window.atob("QQ=="); // = ASCII编码 (缺陷)
let decodedData_2 = window.atob("QQ=="); // = ASCII编码 (缺陷)
console.log(decodedData); //: 
console.log(utf8_to_b64("A")); //: (缺陷)
console.log(b64_to_utf8("QQ==")); //: 必须2**n幂等 //console.log(2 ** 4);//: 2**n幂运算
console.log(b64_to_utf8("QQ")); //: (缺陷)
//
//解决方案 #2 – 重写atob()和btoa()使用TypedArrays 和 UTF-8 : 
//注意:以下代码对于从 Base64 字符串获取ArrayBuffer也很有用,反之亦然(见下文): 
//
"use strict";
// 字节数组到Base64字符串解码 :  
function b64ToUint6(nChr) {
    return nChr > 64 && nChr < 91 ?
        nChr - 65 :
        nChr > 96 && nChr < 123 ?
        nChr - 71 :
        nChr > 47 && nChr < 58 ?
        nChr + 4 :
        nChr === 43 ?
        62 :
        nChr === 47 ?
        63 :
        0;
}

function base64DecToArr(sBase64, nBlocksSize) {
    const sB64Enc = sBase64.replace(/[^A-Za-z0-9+/]/g, "");
    const nInLen = sB64Enc.length;
    const nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2;
    const taBytes = new Uint8Array(nOutLen);

    let nMod3;
    let nMod4;
    let nUint24 = 0;
    let nOutIdx = 0; //let nOutId = 0;
    for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) {
        nMod4 = nInIdx & 3;
        nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 6 * (3 - nMod4);
        if (nMod4 === 3 || nInLen - nInIdx === 1) {
            nMod3 = 0;
            while (nMod3 < 3 && nOutIdx < nOutLen) {
                taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
                nMod3++;
                nOutIdx++;
            }
            nUint24 = 0;

        }
    }

    return taBytes;
}

/* Base64字符串到数组编码 :   */
function uint6ToB64(nUint6) {
    return nUint6 < 26 ?
        nUint6 + 65 :
        nUint6 < 52 ?
        nUint6 + 71 :
        nUint6 < 62 ?
        nUint6 - 4 :
        nUint6 === 62 ?
        43 :
        nUint6 === 63 ?
        47 :
        65;
}

function base64EncArr(aBytes) {
    let nMod3 = 2;
    let sB64Enc = "";

    const nLen = aBytes.length;
    let nUint24 = 0;
    for (let nIdx = 0; nIdx < nLen; nIdx++) {
        nMod3 = nIdx % 3;
        if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) {
            sB64Enc += "\r\n";
        }

        nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
        if (nMod3 === 2 || aBytes.length - nIdx === 1) {
            sB64Enc += String.fromCodePoint(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
            nUint24 = 0;
        }
    }
    return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '==');
}

/* UTF-8数组到JS字符串,反之亦然 :   */

function UTF8ArrToStr(aBytes) {
    let sView = "";
    let nPart;
    const nLen = aBytes.length;
    for (let nIdx = 0; nIdx < nLen; nIdx++) {
        nPart = aBytes[nIdx];
        sView += String.fromCodePoint(
            nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
            /* (nPart - 252 << 30) may be not so safe in ECMAScript! So…: */
            (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 :
            nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
            (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 :
            nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
            (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 :
            nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
            (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 :
            nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
            (nPart - 192 << 6) + aBytes[++nIdx] - 128 :
            /* nPart < 127 ? */
            /* one byte */
            nPart
        );
    }
    return sView;
}

function strToUTF8Arr(sDOMStr) {
    let aBytes;
    let nChr;
    const nStrLen = sDOMStr.length;
    let nArrLen = 0;

    /* mapping… */
    for (let nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {
        nChr = sDOMStr.codePointAt(nMapIdx);

        if (nChr > 65536) {
            nMapIdx++;
        }

        nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6;
    }

    aBytes = new Uint8Array(nArrLen);

    /* 转录 : transcription… */
    let nIdx = 0;
    let nChrIdx = 0;
    while (nIdx < nArrLen) {
        nChr = sDOMStr.codePointAt(nChrIdx);
        if (nChr < 128) {
            /* one byte */
            aBytes[nIdx++] = nChr;
        } else if (nChr < 0x800) {
            /* two bytes */
            aBytes[nIdx++] = 192 + (nChr >>> 6);
            aBytes[nIdx++] = 128 + (nChr & 63);
        } else if (nChr < 0x10000) {
            /* three bytes */
            aBytes[nIdx++] = 224 + (nChr >>> 12);
            aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
            aBytes[nIdx++] = 128 + (nChr & 63);
        } else if (nChr < 0x200000) {
            /* four bytes */
            aBytes[nIdx++] = 240 + (nChr >>> 18);
            aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
            aBytes[nIdx++] = 128 + (nChr & 63);
            nChrIdx++;
        } else if (nChr < 0x4000000) {
            /* five bytes */
            aBytes[nIdx++] = 248 + (nChr >>> 24);
            aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
            aBytes[nIdx++] = 128 + (nChr & 63);
            nChrIdx++;
        } else /* if (nChr <= 0x7fffffff) */ {
            /* six bytes */
            aBytes[nIdx++] = 252 + (nChr >>> 30);
            aBytes[nIdx++] = 128 + (nChr >>> 24 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
            aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
            aBytes[nIdx++] = 128 + (nChr & 63);
            nChrIdx++;
        }
        nChrIdx++;
    }

    return aBytes;
}
// 测试 : 
const sMyInput = "Base 64 \u2014 ";
const aMyUTF8Input = strToUTF8Arr(sMyInput);
const sMyBase64 = base64EncArr(aMyUTF8Input);
console.log(sMyBase64);
//
const aMyUTF8Output = base64DecToArr(sMyBase64);
const sMyOutput = UTF8ArrToStr(aMyUTF8Output);
console.log(sMyOutput);
//
const sMyInput_ = "\ud869\ude95\u3400\u499b\u2a6c7\udec7";
const aMyUTF8Input_ = strToUTF8Arr(sMyInput);
const sMyBase64_ = base64EncArr(aMyUTF8Input);
console.log(sMyBase64_);
// 👪 \ 转义符: (€) &#8364; &#x20AC; &lt; &#60; &amp;(&) (") 表示为&quot; 将单引号 (') 表示为&apos; 
//&#x1F468&#x200D&#x1F469&#x200D&#x1F467&#x200D&#x1F466为了表达'\u1F468\u200D\u1F469\u200D\u1F467\u200D\u1F466'使用16进制或10进制
//&#xd869&#xde95&#x3400&#x499b&#x2a6c7&#xdec7
//&#x2A6C7; ; &#x233B4; 关于UTF-16补充字符与码点 :使用UCS4高低位转换计算后的码点"&#x233B4;"而不是UTF-16的高低位码: &#xD84C;&#xDFB4;
//
// 将 Base64 字符串解码为 Uint8Array 或 ArrayBuffer : 
//函数base64DecToArr(sBase64[, nBlockSize])返回一个uint8字节数组。
//如果您的目标是构建16位/32位/64位原始数据的缓冲区,请使用nBlockSize参数(幂等参数) : 这是uint8Array.buffer所包含的字节数 :
//uint8Array.buffer.bytesLength属性: 
//1、ASCII二进制字符(即字符串中的每个字符都被视为二进制数据8位1个字节的字符)
//2、或UTF-8编码字符串为1个8位,UTF-16字符串为2个8位,UTF-32字符串为4个8位。
// : 字符编码 : 
//
// "Base 64 \u2014 Mozilla Developer Network"
const myArray = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==");
// "Base 64 \u2014 " // : \u2014字节长3 : \u占1个字节、全角字符-占2个字节
const myBuffer = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==").buffer;
console.log(myBuffer.byteLength); //:
//当您从服务器检索文档时,服务器通常会随文档发送一些附加信息。这称为 HTTP 标头。这是一个关于文档信息的示例,该信息通过 HTTP 标头与文档一起从服务器传输到客户端时传递


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专讲冷知识

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值