James 7 月之前
父节点
当前提交
1da03d1481
共有 1 个文件被更改,包括 156 次插入0 次删除
  1. 156 0
      lib/util/base64Utils.dart

+ 156 - 0
lib/util/base64Utils.dart

@@ -0,0 +1,156 @@
+
+import 'dart:convert';
+import 'dart:typed_data';
+import 'package:convert/convert.dart' show hex;
+
+
+
+/// Uint8List <--> Base64
+String bytesToBase64(Uint8List data, {bool urlSafe = false}) {
+  try {
+    if (data.isEmpty) {
+      throw ArgumentError('Input data cannot be empty');
+    }
+
+    final base64Str = base64Encode(data);
+
+    if (urlSafe) {
+      return base64Str
+          .replaceAll('+', '-')
+          .replaceAll('/', '_')
+          .replaceAll('=', '');
+    }
+
+    return base64Str;
+  } on ArgumentError catch (e) {
+    rethrow;
+  } catch (e) {
+    throw Exception('Failed to encode Uint8List to Base64: ${e.toString()}');
+  }
+}
+
+Uint8List base64ToBytes(String base64Str, {bool? urlSafe}) {
+  try {
+    if (base64Str.isEmpty) {
+      throw ArgumentError('Base64 string cannot be empty');
+    }
+    // 如果未指定 urlSafe,自动检测格式
+    final isUrlSafe = urlSafe ??
+        (base64Str.contains('-') || base64Str.contains('_'));
+
+    String normalizedStr = base64Str;
+
+    if (isUrlSafe) {
+      // 添加必要的填充字符
+      final padding = '=' * ((4 - base64Str.length % 4) % 4);
+      normalizedStr = base64Str
+          .replaceAll('-', '+')
+          .replaceAll('_', '/') + padding;
+    }
+
+    // 验证 Base64 字符串格式
+    if (!RegExp(r'^[a-zA-Z0-9+/]*={0,2}$').hasMatch(normalizedStr)) {
+      throw FormatException('Invalid Base64 string format');
+    }
+
+    return base64Decode(normalizedStr);
+  } on ArgumentError catch (e) {
+    rethrow;
+  } on FormatException catch (e) {
+    rethrow;
+  } catch (e) {
+    throw Exception('Failed to decode Base64 to Uint8List: ${e.toString()}');
+  }
+}
+
+
+
+/// 将十六进制字符串直接转换为 Base64
+///
+/// [hexStr] 十六进制字符串
+/// [urlSafe] 是否生成URL安全的Base64
+///
+/// 返回 Base64 字符串或抛出异常
+String hexToBase64(String hexStr, {bool urlSafe = false}) {
+  try {
+    if (hexStr.isEmpty) {
+      throw ArgumentError('Hex string cannot be empty');
+    }
+
+    final normalizedHex = hexStr.startsWith('0x')
+        ? hexStr.substring(2)
+        : hexStr;
+
+    if (!RegExp(r'^[0-9a-fA-F]+$').hasMatch(normalizedHex)) {
+      throw FormatException('Invalid hex string format');
+    }
+
+    final bytes = hex.decode(normalizedHex.padLeft(
+        normalizedHex.length + normalizedHex.length % 2,
+        '0'
+    ));
+
+    final base64 = base64Encode(bytes);
+    return urlSafe
+        ? base64.replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '')
+        : base64;
+  } on ArgumentError catch (e) {
+    rethrow;
+  } on FormatException catch (e) {
+    rethrow;
+  } catch (e) {
+    throw Exception('Failed to convert hex to Base64: ${e.toString()}');
+  }
+}
+
+
+/// 将 Base64 字符串转换为十六进制字符串
+///
+/// [base64Str] 输入的 Base64 字符串
+/// [urlSafe] 输入是否是 URL 安全的 Base64 编码
+/// [withPrefix] 是否添加 "0x" 前缀
+///
+/// 返回十六进制字符串或抛出异常
+String base64ToHex(String base64Str, {
+  bool urlSafe = false,
+  bool withPrefix = false,
+}) {
+  try {
+    if (base64Str.isEmpty) {
+      throw ArgumentError('Base64 string cannot be empty');
+    }
+
+    String normalizedStr = base64Str;
+
+    // 处理 URL 安全的 Base64
+    if (urlSafe) {
+      // 添加必要的填充字符
+      final padding = '=' * ((4 - base64Str.length % 4) % 4);
+      normalizedStr = base64Str
+          .replaceAll('-', '+')
+          .replaceAll('_', '/') + padding;
+    }
+
+    // 验证 Base64 字符串格式
+    if (!RegExp(r'^[a-zA-Z0-9+/]*={0,2}$').hasMatch(normalizedStr)) {
+      throw FormatException('Invalid Base64 string format');
+    }
+
+    // 解码为字节数组
+    final bytes = base64Decode(normalizedStr);
+
+    // 转换为十六进制
+    final hexString = bytes.map((byte) {
+      return byte.toRadixString(16).padLeft(2, '0');
+    }).join('');
+
+    return withPrefix ? '0x$hexString' : hexString;
+  } on ArgumentError catch (e) {
+    rethrow;
+  } on FormatException catch (e) {
+    rethrow;
+  } catch (e) {
+    throw Exception('Failed to convert Base64 to hex: ${e.toString()}');
+  }
+}
+