using MAX.Core.DependencyInjection; using Microsoft.Extensions.Configuration; using System.IO.Compression; using System.Text; namespace Store.Modules.CloudProduct.Services { /// /// 商品原始数据文件存储:按 goodsId % 100 分目录,文件名即商品ID,GZip 压缩保存。 /// public interface IRawDataStorage : IScopedDependency { /// /// 保存原始数据,返回保存后的完整路径。 /// Task SaveAsync(long goodsId, string rawData); /// /// 读取并解压原始数据;文件不存在时返回 null。 /// Task ReadAsync(long goodsId); /// /// 判断指定商品的原始数据文件是否存在。 /// bool Exists(long goodsId); } internal class RawDataStorage : IRawDataStorage { private readonly string _rootPath; public RawDataStorage(IConfiguration configuration) { var configured = configuration.GetValue("RawData:Path"); if (string.IsNullOrWhiteSpace(configured)) configured = "RawData"; _rootPath = Path.GetFullPath(configured); } /// public async Task SaveAsync(long goodsId, string rawData) { var filePath = GetFilePath(goodsId); var dir = Path.GetDirectoryName(filePath)!; Directory.CreateDirectory(dir); await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None); await using var gzip = new GZipStream(fileStream, CompressionLevel.Fastest); await using var writer = new StreamWriter(gzip, new UTF8Encoding(false)); await writer.WriteAsync(rawData); return filePath; } /// public async Task ReadAsync(long goodsId) { var filePath = GetFilePath(goodsId); if (!File.Exists(filePath)) return null; await using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); await using var gzip = new GZipStream(fileStream, CompressionMode.Decompress); using var reader = new StreamReader(gzip, new UTF8Encoding(false)); return await reader.ReadToEndAsync(); } /// public bool Exists(long goodsId) { return File.Exists(GetFilePath(goodsId)); } private string GetFilePath(long goodsId) { var subDir = (goodsId % 100).ToString(); return Path.Combine(_rootPath, subDir, goodsId.ToString()); } } }