fenghuo/packages/tus/src/utils/models/Metadata.ts

105 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string, string | null> = {};
// 如果字符串为空或仅包含空白字符,则无效
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<Upload['metadata']>): 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(',');
}