/** * 本库提供几个常用方法: * 1、enDecodeTools.uniEncode(text); 将中文进行Unicode编码并输出 * 2、enDecodeTools.base64Encode(text); 将文字进行base64编码并输出 * 3、enDecodeTools.base64Decode(text); 将经过base64编码的文字进行base64解码并输出 * 4、enDecodeTools.utf8Encode(text); 将文字进行utf-8编码并输出 * 5、enDecodeTools.utf8Decode(text); 将经过utf-8编码的文字进行utf-8解码并输出 */ import Md5Utils from './md5.js'; let EncodeUtils = (() => { //base64编码字符集 let _base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //base64解码字符集 let _base64DecodeChars = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; /** * 此方法实现中文向Unicode的转码,与Jre中的"native2ascii"命令一样 * @param {String} text 需要进行转码的字符串 * @return {String} Unicode码 */ let _uniEncode = function (text) { let res = []; for (let i = 0; i < text.length; i++) { res[i] = ("00" + text.charCodeAt(i).toString(16)).slice(-4); } return "\\u" + res.join("\\u"); }; /** * 此方法用于将Unicode码解码为正常字符串 * @param {Object} text */ let _uniDecode = function (text) { text = text = text.replace(/(\\)?\\u/gi, "%u").replace('%u0025', '%25'); text = unescape(text.toString().replace(/%2B/g, "+")); let matches = text.match(/(%u00([0-9A-F]{2}))/gi); if (matches) { for (let matchid = 0; matchid < matches.length; matchid++) { let code = matches[matchid].substring(1, 3); let x = Number("0x" + code); if (x >= 128) { text = text.replace(matches[matchid], code); } } } text = unescape(text.toString().replace(/%2B/g, "+")); return text; }; /** * 此方法用于将文字进行UTF-8编码 * @param {Object} str 源码 * @return {String} UTF-8码 */ let _utf8Encode = function (str) { let out, i, len, c; out = ""; len = str.length; for (i = 0; i < len; i++) { c = str.charCodeAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out += str.charAt(i); } else if (c > 0x07FF) { out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } else { out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } } return out; }; /** * 此方法用于将文字进行UTF-8解码 * @param {Object} str * @return {String} 原文字 */ let _utf8Decode = function (str) { let out, i, len, c; let char2, char3; out = ""; len = str.length; i = 0; while (i < len) { c = str.charCodeAt(i++); switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += str.charAt(i - 1); break; case 12: case 13: // 110x xxxx  10xx xxxx char2 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = str.charCodeAt(i++); char3 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; }; /** * 此方法用于将文字进行base64编码 * @param {Object} str 源码 * @return {String} base64码 */ let _base64Encode = function (str) { let out, i, len; let c1, c2, c3; len = str.length; i = 0; out = ""; while (i < len) { c1 = str.charCodeAt(i++) & 0xff; if (i == len) { out += _base64EncodeChars.charAt(c1 >> 2); out += _base64EncodeChars.charAt((c1 & 0x3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if (i == len) { out += _base64EncodeChars.charAt(c1 >> 2); out += _base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += _base64EncodeChars.charAt((c2 & 0xF) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += _base64EncodeChars.charAt(c1 >> 2); out += _base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += _base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); out += _base64EncodeChars.charAt(c3 & 0x3F); } return out; }; /** * 此方法用于将文字进行base64解码 * @param {Object} str 源码 * @return {String} 源码 */ let _base64Decode = function (str) { let c1, c2, c3, c4; let i, len, out; len = str.length; i = 0; out = ""; while (i < len) { /* c1 */ do { c1 = _base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c1 == -1); if (c1 == -1) break; /* c2 */ do { c2 = _base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c2 == -1); if (c2 == -1) break; out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); /* c3 */ do { c3 = str.charCodeAt(i++) & 0xff; if (c3 == 61) return out; c3 = _base64DecodeChars[c3]; } while (i < len && c3 == -1); if (c3 == -1) break; out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); /* c4 */ do { c4 = str.charCodeAt(i++) & 0xff; if (c4 == 61) return out; c4 = _base64DecodeChars[c4]; } while (i < len && c4 == -1); if (c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4); } return out; }; /** * 中文,一般情况下Unicode是UTF-16实现,长度2位,而UTF-8编码是3位 * @param str * @return {String} */ let _utf16to8 = function (str) { return str.replace(/\\x/g, '%'); }; let _utf8to16 = function (str) { return str.replace(/%/g, '\\x'); }; /** * md5加密 * @param str */ let md5 = (str) => { return Md5Utils.md5(str); }; /** * 字符串与Hex编码互转 * @param input * @returns {string} */ let hexTools = (function (input) { let utf8encode = function (str, isGetBytes) { let back = []; let byteSize = 0; for (let i = 0; i < str.length; i++) { let code = str.charCodeAt(i); if (0x00 <= code && code <= 0x7f) { byteSize += 1; back.push(code); } else if (0x80 <= code && code <= 0x7ff) { byteSize += 2; back.push((192 | (31 & (code >> 6)))); back.push((128 | (63 & code))) } else if ((0x800 <= code && code <= 0xd7ff) || (0xe000 <= code && code <= 0xffff)) { byteSize += 3; back.push((224 | (15 & (code >> 12)))); back.push((128 | (63 & (code >> 6)))); back.push((128 | (63 & code))) } } for (let i = 0; i < back.length; i++) { back[i] &= 0xff; } if (isGetBytes) { return back } if (byteSize <= 0xff) { return [0, byteSize].concat(back); } else { return [byteSize >> 8, byteSize & 0xff].concat(back); } }; let utf8decode = function (arr) { if (typeof arr === 'string') { return arr; } let UTF = '', _arr = arr; for (let i = 0; i < _arr.length; i++) { let one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length === 8) { let bytesLength = v[0].length; let store = _arr[i].toString(2).slice(7 - bytesLength); for (let st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2) } UTF += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1 } else { UTF += String.fromCharCode(_arr[i]) } } return UTF }; let hexEncode = function (str) { let charBuf = utf8encode(str, true); let re = ''; for (let i = 0; i < charBuf.length; i++) { let x = (charBuf[i] & 0xFF).toString(16); if (x.length === 1) { x = '0' + x; } re += x; } return re; }; let hexDecode = function (str) { let buf = []; for (let i = 0; i < str.length; i += 2) { buf.push(parseInt(str.substring(i, i + 2), 16)); } return utf8decode(buf); }; return {hexEncode, hexDecode}; })(); /** * html代码转换成js * @param txt * @returns {string} */ let _html2js = function (txt) { let htmlArr = txt.replace(/\\/g, "\\\\").replace(/\\/g, "\\/").replace(/\'/g, "\\\'").split('\n'); let len = htmlArr.length; let outArr = []; outArr.push("let htmlCodes = [\n"); htmlArr.forEach((value, index) => { if (value !== "") { if (index === len - 1) { outArr.push("\'" + value + "\'"); } else { outArr.push("\'" + value + "\',\n"); } } }); outArr.push("\n].join(\"\");"); return outArr.join(""); }; /** * URL 参数解析 * @param url * @returns {{url: *, params: Array}} * @private */ let _urlParamsDecode = function (url) { let res = {}; try { let params = []; let urlObj = new URL(url); for (let item of urlObj.searchParams) { params.push(item); } res = { url: urlObj.href, params: params, protocol: urlObj.protocol, pathname: urlObj.pathname, hostname: urlObj.hostname } } catch (e) { res.error = '这不是一个合法的URL!无法完成解析!' } return res; }; // sha1加密 let _sha1Encode = function (str) { function encodeUTF8(s) { let i, r = [], c, x; for (i = 0; i < s.length; i++) if ((c = s.charCodeAt(i)) < 0x80) r.push(c); else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F)); else { if ((x = c ^ 0xD800) >> 10 == 0) c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000, r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F)); else r.push(0xE0 + (c >> 12 & 0xF)); r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F)); } return r; } var data = new Uint8Array(encodeUTF8(str)) var i, j, t; var l = ((data.length + 8) >>> 6 << 4) + 16, s = new Uint8Array(l << 2); s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer); for (t = new DataView(s.buffer), i = 0; i < l; i++)s[i] = t.getUint32(i << 2); s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8); s[l - 1] = data.length << 3; var w = [], f = [ function () { return m[1] & m[2] | ~m[1] & m[3]; }, function () { return m[1] ^ m[2] ^ m[3]; }, function () { return m[1] & m[2] | m[1] & m[3] | m[2] & m[3]; }, function () { return m[1] ^ m[2] ^ m[3]; } ], rol = function (n, c) { return n << c | n >>> (32 - c); }, k = [1518500249, 1859775393, -1894007588, -899497514], m = [1732584193, -271733879, null, null, -1009589776]; m[2] = ~m[0], m[3] = ~m[1]; for (i = 0; i < s.length; i += 16) { var o = m.slice(0); for (j = 0; j < 80; j++) w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1), t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0, m[1] = rol(m[1], 30), m.pop(), m.unshift(t); for (j = 0; j < 5; j++)m[j] = m[j] + o[j] | 0; }; t = new DataView(new Uint32Array(m).buffer); for (var i = 0; i < 5; i++)m[i] = t.getUint32(i << 2); var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) { return (e < 16 ? "0" : "") + e.toString(16); }).join(""); return hex; }; // 来自网友的贡献,做jwt解码 let jwtDecode = (() => { class InvalidTokenError extends Error { } InvalidTokenError.prototype.name = "InvalidTokenError"; function b64DecodeUnicode(str) { return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => { let code = p.charCodeAt(0).toString(16).toUpperCase(); if (code.length < 2) { code = "0" + code; } return "%" + code; })); } function base64UrlDecode(str) { let output = str.replace(/-/g, "+").replace(/_/g, "/"); switch (output.length % 4) { case 0: break; case 2: output += "=="; break; case 3: output += "="; break; default: throw new Error("base64 string is not of the correct length"); } try { return b64DecodeUnicode(output); } catch (err) { return atob(output); } } return function(token) { if (typeof token !== "string") { throw new InvalidTokenError("Invalid token specified: must be a string"); } const parts = token.split("."); if (parts.length !== 3) { throw new InvalidTokenError("Invalid token specified: must be three parts"); } for(let part of parts){ if (typeof part !== "string") { throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`); } } return { header: base64UrlDecode(parts[0]), payload: base64UrlDecode(parts[1]), sign: parts[2] } } })(); /** * 将cookie字符串格式化为JSON对象 * @param {string} cookieString - 原始的cookie字符串 * @returns {string} 格式化后的JSON字符串 */ let formatCookieStringToJson = (cookieString) => { // 将原始cookie字符串分割成各个键值对,并解析为JSON对象 const cookiesArray = cookieString.split(';').map(pair => { const [key, value] = pair.trim().split('='); let obj = {},dk , vk ; try { dk = decodeURIComponent(key); vk = decodeURIComponent(value); } catch (error) { dk = key; vk = value; } obj[dk] = vk; return obj; }).reduce((accumulator, current) => { // 合并所有键值对到一个对象中 const key = Object.keys(current)[0]; accumulator[key] = current[key]; return accumulator; }, {}); // 返回格式化的JSON return cookiesArray; } /** * 使用gzip压缩文本(返回Base64编码的结果) * @param {string} text - 需要压缩的文本 * @returns {Promise} 压缩后的Base64字符串 */ let _gzipEncode = async function(text) { try { // 检查浏览器是否支持CompressionStream API if (typeof CompressionStream === 'undefined') { throw new Error('当前浏览器不支持CompressionStream API,请使用Chrome 80+、Firefox 113+或Safari 16.4+'); } // 将文本转换为Uint8Array const encoder = new TextEncoder(); const data = encoder.encode(text); // 创建压缩流 const compressionStream = new CompressionStream('gzip'); const compressedStream = new Response(data).body.pipeThrough(compressionStream); // 读取压缩后的数据 const compressedArrayBuffer = await new Response(compressedStream).arrayBuffer(); // 将ArrayBuffer转换为Base64字符串 const compressedArray = new Uint8Array(compressedArrayBuffer); let binaryString = ''; for (let i = 0; i < compressedArray.length; i++) { binaryString += String.fromCharCode(compressedArray[i]); } return btoa(binaryString); } catch (error) { throw new Error('Gzip压缩失败: ' + error.message); } }; /** * 使用gzip解压缩Base64编码的数据 * @param {string} compressedBase64 - Base64编码的压缩数据 * @returns {Promise} 解压缩后的文本 */ let _gzipDecode = async function(compressedBase64) { try { // 检查浏览器是否支持DecompressionStream API if (typeof DecompressionStream === 'undefined') { throw new Error('当前浏览器不支持DecompressionStream API,请使用Chrome 80+、Firefox 113+或Safari 16.4+'); } // 将Base64字符串转换为Uint8Array const binaryString = atob(compressedBase64); const compressedArray = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { compressedArray[i] = binaryString.charCodeAt(i); } // 创建解压缩流 const decompressionStream = new DecompressionStream('gzip'); const decompressedStream = new Response(compressedArray).body.pipeThrough(decompressionStream); // 读取解压缩后的数据 const decompressedArrayBuffer = await new Response(decompressedStream).arrayBuffer(); // 将ArrayBuffer转换为文本 const decoder = new TextDecoder(); return decoder.decode(decompressedArrayBuffer); } catch (error) { throw new Error('Gzip解压缩失败: ' + error.message); } }; return { uniEncode: _uniEncode, uniDecode: _uniDecode, base64Encode: _base64Encode, base64Decode: _base64Decode, utf8Encode: _utf8Encode, utf8Decode: _utf8Decode, utf16to8: _utf16to8, utf8to16: _utf8to16, md5: md5, hexEncode: hexTools.hexEncode, hexDecode: hexTools.hexDecode, html2js: _html2js, urlParamsDecode: _urlParamsDecode, sha1Encode: _sha1Encode, jwtDecode, formatCookieStringToJson, gzipEncode: _gzipEncode, gzipDecode: _gzipDecode }; })(); export default EncodeUtils;