Last active
November 7, 2025 07:08
-
-
Save nuintun/7508b9ddd8421e66f5e6 to your computer and use it in GitHub Desktop.
用 XMLDOM 和 ADODB.Stream 实现base64编码解码
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Base64 | |
| * http://blog.csdn.net/cuixiping/article/details/409468 | |
| * ADODB.Stream 实例有 LoadFromFile 方法可以读取文件内容 | |
| * ADODB.Stream 实例有 state 属性 0 和 1,分别对应 Open 状态: adStateClosed 和 adStateOpen | |
| * ADODB.Stream 实例有 LineSeparator 属性 13、-1 和 10,分别对应换行符: adCR、adCRLF 和 adLF | |
| * ADODB.Stream 实例的其他属性和方法可参考相应文档 | |
| */ | |
| var Base64 = { | |
| /** | |
| * Base64 encode | |
| * | |
| * @param string | |
| * @returns {Base64} | |
| */ | |
| encode: function(string) { | |
| var base64; | |
| var xmldom = new ActiveXObject('MSXML2.DOMDocument'); | |
| var adostream = new ActiveXObject('ADODB.Stream'); | |
| var stream = xmldom.createElement('stream'); | |
| stream.dataType = 'bin.base64'; | |
| adostream.Charset = 'utf-8'; | |
| // 1=adTypeBinary 2=adTypeText | |
| adostream.Type = 2; | |
| adostream.Open(); | |
| adostream.WriteText(string); | |
| adostream.Position = 0; | |
| // 1=adTypeBinary 2=adTypeText | |
| adostream.Type = 1; | |
| // -1=adReadAll | |
| stream.nodeTypedValue = adostream.Read(-1); | |
| base64 = stream.text; | |
| adostream.Close(); | |
| // clean | |
| stream = null; | |
| adostream = null; | |
| xmldom = null; | |
| return base64; | |
| }, | |
| /** | |
| * Base64 decode | |
| * | |
| * @param base64 | |
| * @returns {String} | |
| */ | |
| decode: function(base64) { | |
| var string; | |
| var xmldom = new ActiveXObject('MSXML2.DOMDocument'); | |
| var adostream = new ActiveXObject('ADODB.Stream'); | |
| var stream = xmldom.createElement('stream'); | |
| stream.dataType = 'bin.base64'; | |
| stream.text = base64; | |
| adostream.Charset = 'utf-8'; | |
| // 1=adTypeBinary 2=adTypeText | |
| adostream.Type = 1; | |
| adostream.Open(); | |
| adostream.Write(stream.nodeTypedValue); | |
| adostream.Position = 0; | |
| // 1=adTypeBinary 2=adTypeText | |
| adostream.Type = 2; | |
| // -1=adReadAll | |
| string = adostream.ReadText(-1); | |
| adostream.Close(); | |
| // clean | |
| stream = null; | |
| adostream = null; | |
| xmldom = null; | |
| return string; | |
| } | |
| }; |
Author
nuintun
commented
Oct 15, 2025
Author
/**
* @module base64
*/
import { isFunction } from './utils';
export interface EncodeOptions {
/**
* @description 使用的 Base64 字母表
* @default 'base64'
*/
alphabet?: 'base64' | 'base64url';
/**
* 是否省略编码字符串末尾的填充字符 (=)
* @default false
*/
omitPadding?: boolean;
}
export interface DecodeOptions {
/**
* @description 用于编码字符串的 Base64 字母表
* @default 'base64'
*/
alphabet?: 'base64' | 'base64url';
/**
* @description 如何处理 Base64 字符串的最后一个块
* @default 'loose'
*/
lastChunkHandling?: 'loose' | 'strict';
}
/**
* @function encode
* @description 将 Uint8Array 转换为 base64 字符串
* @param {Uint8Array} bytes 需要转换的字节数组
* @param {EncodeOptions} [options] 编码选项
* @returns {string} base64 字符串
*/
export function encode(bytes: Uint8Array, options?: EncodeOptions): string {
// @ts-expect-error
if (isFunction(bytes.toBase64)) {
// @ts-expect-error
return bytes.toBase64(options);
}
// 二进制字符串
let binary = '';
// 获取字节数组的长度
const length = bytes.length;
// 填充二进制字符串
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
// 使用 btoa 转换为 base64
let base64 = btoa(binary);
// 如果使用 base64url 编码
if (options?.alphabet === 'base64url') {
// 替换 + 和 / 为 - 和 _
base64 = base64.replace(/[+/]/g, char => {
return char === '+' ? '-' : '_';
});
// 如果省略填充字符
if (options?.omitPadding) {
base64 = base64.replace(/=+$/, '');
}
}
// 返回 base64 字符串
return base64;
}
/**
* @function decode
* @description 将 base64 字符串转换为 Uint8Array
* @param {string} base64 base64 字符串
* @param {DecodeOptions} [options] 解码选项
* @returns {Uint8Array} 转换后的字节数组
*/
export function decode(base64: string, options?: DecodeOptions): Uint8Array {
// @ts-expect-error
if (isFunction(Uint8Array.fromBase64)) {
// @ts-expect-error
return Uint8Array.fromBase64(base64, options);
}
// 删除首尾空白
let normalized = base64.trim();
// 根据 alphabet 选项处理字符转换
if (options?.alphabet === 'base64url') {
// 使用字符映射优化替换操作
normalized = normalized.replace(/[-_]/g, char => {
return char === '-' ? '+' : '/';
});
}
// 如果为 strict 模式,进行长度检查
if (options?.lastChunkHandling === 'strict') {
// 检查长度是否满足 4 的倍数
if (normalized.length % 4 !== 0) {
throw new SyntaxError('The base64 input terminates with a single character, excluding padding (=)');
}
}
// 使用 atob 解码
const binary = atob(normalized);
// 获取字节数组的长度
const length = binary.length;
// 创建字节数组
const bytes = new Uint8Array(length);
// 填充字节数组
for (let i = 0; i < length; i++) {
bytes[i] = binary.charCodeAt(i);
}
// 返回字节数组
return bytes;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment