Stream流应用
对上传zip压缩文本文件解析,引用第三方包SharpZipLib,写了一个静态扩展类。主要是对Stream流的基本操作方便下次翻看,代码如下:
1 using ICSharpCode.SharpZipLib.Zip; 2 using Microsoft.AspNetCore.Http; 3 using System; 4 using System.Collections.Generic; 5 using System.IO; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace Extensions 10 { 11 /// <summary> 12 /// Zip辅助类 13 /// </summary> 14 public static class ZipHelperExtension 15 { 16 /// <summary> 17 /// 解压单zip压缩文件 18 /// </summary> 19 /// <param name="sourceFile">压缩文件</param> 20 /// <param name="contentHandle">文本内容处理</param> 21 /// <returns>压缩的所有文件处理结果</returns> 22 public static async Task<(IList<T> modelList, string errMessage)> UnZipFileAsync<T>(IFormFile sourceFile, 23 Func<string, Task<T>> contentHandle) where T : class 24 { 25 var err = string.Empty; 26 var modelList = new List<T>(); 27 try 28 { 29 await using ZipInputStream zipIn = new(sourceFile.OpenReadStream()); 30 31 var models = await UnZipAsync(zipIn, contentHandle); 32 modelList.AddRange(models); 33 } 34 catch (Exception ex) 35 { 36 err = $"错误信息=>{sourceFile.Name}:{ex.Message};"; 37 } 38 39 return (modelList, err); 40 } 41 42 /// <summary> 43 /// 批量解压zip压缩文件 44 /// </summary> 45 /// <param name="sourceFiles">压缩文件</param> 46 /// <param name="contentHandle">文本内容处理</param> 47 /// <returns>压缩的所有文件处理结果</returns> 48 public static async Task<(IList<T> list, string err)> UnZipFilesAsync<T>(IFormFileCollection sourceFiles, 49 Func<string, Task<T>> contentHandle) where T : class 50 { 51 var err = string.Empty; 52 var list = new List<T>(); 53 foreach (var sourceFile in sourceFiles) 54 { 55 var (modelList, errMessage) = await UnZipFileAsync(sourceFile, contentHandle); 56 list.AddRange(modelList); 57 err += errMessage; 58 } 59 60 return (list, err); 61 } 62 63 /// <summary> 64 /// 处理zip压缩文件内容 65 /// </summary> 66 /// <param name="zipIn">压缩文件流</param> 67 /// <param name="contentHandle">文本内容处理</param> 68 /// <returns>压缩的所有文件处理结果集合</returns> 69 public static async Task<IEnumerable<T>> UnZipAsync<T>(ZipInputStream zipIn, 70 Func<string, Task<T>> contentHandle) where T : class 71 { 72 var list = new List<T>(); 73 while (zipIn.GetNextEntry() != null) 74 { 75 Stream stream = new MemoryStream(); 76 await using var bos = new BinaryWriter(stream, Encoding.Default, leaveOpen: false); 77 78 var bytes = new byte[1024]; 79 while (true) 80 { 81 var len = await zipIn.ReadAsync(bytes); 82 if (len <= 0) 83 { 84 break; 85 } 86 87 bos.Write(bytes, 0, len); 88 bos.Flush(); 89 } 90 91 if (stream.Length == 0) continue;//过滤文件夹 92 stream.Position = 0; 93 var content = await GetTextStreamContentAsync(stream); 94 var model = await contentHandle(content); 95 list.Add(model); 96 } 97 98 return list; 99 } 100 101 /// <summary> 102 /// 获取文本流 103 /// </summary> 104 /// <param name="str">字符串</param> 105 /// <returns>文本流</returns> 106 public static async Task<Stream> GetStreamAsync(this string str) 107 { 108 var stream = new MemoryStream(); 109 //leaveOpen:true使StreamWriter释放而stream不会释放 110 await using var writer = new StreamWriter(stream, leaveOpen: true); 111 112 await writer.WriteAsync(str); 113 await writer.FlushAsync(); 114 115 stream.Position = 0; 116 return stream; 117 } 118 119 /// <summary> 120 /// 获取文本流内容 121 /// </summary> 122 /// <param name="textStream">文本流</param> 123 /// <returns>文本流内容</returns> 124 public static async Task<string> GetTextStreamContentAsync(Stream textStream) 125 { 126 using var reader = new StreamReader(textStream); 127 return await reader.ReadToEndAsync(); 128 } 129 } 130 }
上传文件测试一下用法:
1 /// <summary> 2 /// 解压zip测试 3 /// </summary> 4 /// <param name="zipFile">压缩文件</param> 5 /// <returns></returns> 6 [HttpPost("unzip-test")] 7 //这个注意IFormFile,IFormFileCollection类型前面不需要直接加[FromForm]特性,否者swagger不支持上传文件 8 //可以将表单所有参数(包括文件IFormFile,IFormFileCollection)封装一个参数对象,前面加[FromForm]特性 9 public async Task UnzipTest(IFormFile zipFile) 10 { 11 var (persons, errMessage) = await ZipHelperExtension.UnZipFileAsync(zipFile, 12 async content => 13 { 14 var person = JsonConvert.DeserializeObject<Person>(content); 15 person?.Pets.Add(new Pet() { Name = "小猪", Age = 5 }); 16 person?.Pets.ForEach(p => p.Master = person); 17 return await Task.FromResult(person); 18 }); 19 _logger.LogInformation(string.Join("\n", persons)); 20 }
结果: