Base64StreamingEncoder.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace PTMedicalInsurance.Common
  8. {
  9. public static class Base64StreamingEncoder
  10. {
  11. /// <summary>
  12. /// 将文件以流式方式转换为 Base64 字符串(适用于大文件)
  13. /// </summary>
  14. /// <param name="inputFilePath">输入 ZIP 文件路径</param>
  15. /// <param name="outputWriter">输出目标(如 StreamWriter、StringWriter 或网络流)</param>
  16. /// <param name="chunkSize">每次读取的字节数(建议 3 的倍数,如 36864)</param>
  17. public static void ConvertToBase64Stream(string inputFilePath, TextWriter outputWriter, int chunkSize = 36864)
  18. {
  19. // 确保 chunkSize 是 3 的倍数,避免 Base64 编码时出现填充混乱(可选优化)
  20. if (chunkSize % 3 != 0)
  21. throw new ArgumentException("chunkSize 最好是 3 的倍数,以提高 Base64 效率。");
  22. byte[] buffer = new byte[chunkSize];
  23. int bytesRead;
  24. // 保留未完全编码的字节(用于跨块对齐)
  25. var leftoverBuffer = new byte[2]; // Base64 每 3 字节一组,最多余 2 字节
  26. int leftoverCount = 0;
  27. using (var fileStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: false))
  28. {
  29. while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
  30. {
  31. // 当前块 + 上次剩余字节,组成完整处理单元
  32. int totalAvailable = leftoverCount + bytesRead;
  33. var processBuffer = new byte[totalAvailable];
  34. Array.Copy(leftoverBuffer, 0, processBuffer, 0, leftoverCount);
  35. Array.Copy(buffer, 0, processBuffer, leftoverCount, bytesRead);
  36. // 计算可以完整编码的字节数(必须是 3 的倍数)
  37. int fullGroups = (totalAvailable / 3) * 3;
  38. int remaining = totalAvailable - fullGroups;
  39. // 编码完整组
  40. string encoded = Convert.ToBase64String(processBuffer, 0, fullGroups);
  41. outputWriter.Write(encoded);
  42. // 保存剩余字节(用于下一次)
  43. Array.Clear(leftoverBuffer, 0, leftoverBuffer.Length);
  44. Array.Copy(processBuffer, fullGroups, leftoverBuffer, 0, remaining);
  45. leftoverCount = remaining;
  46. }
  47. // 处理最后的剩余字节(会自动补 '=')
  48. if (leftoverCount > 0)
  49. {
  50. string final = Convert.ToBase64String(leftoverBuffer, 0, leftoverCount);
  51. outputWriter.Write(final);
  52. }
  53. }
  54. }
  55. }
  56. }