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 ///12 /// Zip辅助类 13 /// 14 public static class ZipHelperExtension 15 { 16 /// 17 /// 解压单zip压缩文件 18 /// 19 /// 压缩文件 20 /// 文本内容处理 21 /// 压缩的所有文件处理结果 22 public static async Task<(IList modelList, string errMessage)> UnZipFileAsync (IFormFile sourceFile, 23 Func<string, Task > contentHandle) where T : class 24 { 25 var err = string.Empty; 26 var modelList = new List (); 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 /// 43 /// 批量解压zip压缩文件 44 /// 45 /// 压缩文件 46 /// 文本内容处理 47 /// 压缩的所有文件处理结果 48 public static async Task<(IList list, string err)> UnZipFilesAsync (IFormFileCollection sourceFiles, 49 Func<string, Task > contentHandle) where T : class 50 { 51 var err = string.Empty; 52 var list = new List (); 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 /// 64 /// 处理zip压缩文件内容 65 /// 66 /// 压缩文件流 67 /// 文本内容处理 68 /// 压缩的所有文件处理结果集合 69 public static async Task > UnZipAsync (ZipInputStream zipIn, 70 Func<string, Task > contentHandle) where T : class 71 { 72 var list = new List (); 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 /// 102 /// 获取文本流 103 /// 104 /// 字符串 105 /// 文本流 106 public static async Task 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 /// 120 /// 获取文本流内容 121 /// 122 /// 文本流 123 /// 文本流内容 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 ///2 /// 解压zip测试 3 /// 4 /// 压缩文件 5 /// 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 (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 }
结果: