import type { Upload } from './Upload'; // 定义ASCII码中的空格和逗号字符的码点 const ASCII_SPACE = ' '.codePointAt(0); const ASCII_COMMA = ','.codePointAt(0); // 定义用于验证Base64字符串的正则表达式 const BASE64_REGEX = /^[\d+/A-Za-z]*={0,2}$/; /** * 验证元数据键的有效性 * @param key 需要验证的键 * @returns 如果键有效则返回true,否则返回false */ export function validateKey(key: string) { // 如果键的长度为0,则无效 if (key.length === 0) { return false; } // 遍历键的每个字符,检查其码点是否在有效范围内 for (let i = 0; i < key.length; ++i) { const charCodePoint = key.codePointAt(i) as number; if ( charCodePoint > 127 || // 非ASCII字符 charCodePoint === ASCII_SPACE || // 空格字符 charCodePoint === ASCII_COMMA // 逗号字符 ) { return false; } } return true; } /** * 验证元数据值的有效性 * @param value 需要验证的值 * @returns 如果值是有效的Base64字符串则返回true,否则返回false */ export function validateValue(value: string) { // Base64字符串的长度必须是4的倍数 if (value.length % 4 !== 0) { return false; } // 使用正则表达式验证Base64字符串的格式 return BASE64_REGEX.test(value); } /** * 解析元数据字符串 * @param str 需要解析的元数据字符串 * @returns 返回解析后的元数据对象 * @throws 如果元数据字符串无效则抛出错误 */ export function parse(str?: string) { const meta: Record = {}; // 如果字符串为空或仅包含空白字符,则无效 if (!str || str.trim().length === 0) { throw new Error('Metadata string is not valid'); } // 遍历字符串中的每个键值对 for (const pair of str.split(',')) { const tokens = pair.split(' '); const [key, value] = tokens; // 验证键和值的有效性,并确保键在元数据对象中不存在 if ( key && ((tokens.length === 1 && validateKey(key)) || (tokens.length === 2 && validateKey(key) && value && validateValue(value))) && !(key in meta) ) { // 如果值存在,则将其从Base64解码为UTF-8字符串 const decodedValue = value ? Buffer.from(value, 'base64').toString('utf8') : null; meta[key] = decodedValue; } else { throw new Error('Metadata string is not valid'); } } return meta; } /** * 将元数据对象序列化为字符串 * @param metadata 需要序列化的元数据对象 * @returns 返回序列化后的元数据字符串 */ export function stringify(metadata: NonNullable): string { return Object.entries(metadata) .map(([key, value]) => { // 如果值为null,则仅返回键 if (value === null) { return key; } // 将值编码为Base64字符串,并与键组合 const encodedValue = Buffer.from(value, 'utf8').toString('base64'); return `${key} ${encodedValue}`; }) .join(','); }