.NET环境下复用web请求响应流实现多操作的技术咨询
解决方案
完全可以实现,无需二次发起请求、也无需读取本地磁盘文件就能完成业务模型转换。
实现原理
网络请求返回的响应流默认是只进只读的流,读取一次后游标就会移动到流末尾,无法再次读取。你当前的代码直接将响应流拷贝到文件流,读取完成后响应流就不可复用,只要先把响应流转存到支持随机访问的中间流(比如MemoryStream)就能解决这个问题。
修改后代码示例
public async ValueTask<YourBusinessModel> GetWeatherByLocation(string place) { try { const string locationEndpoint = "https://localhost/api/place/?query="; var fullEndpoint = $"{locationEndpoint}{place}"; HttpWebRequest request = WebRequest.CreateHttp(fullEndpoint); WebResponse response = await request.GetResponseAsync(); ContentDispositionHeaderValue contentDisposition; var fileName = ContentDispositionHeaderValue.TryParse(response.Headers["Content-Disposition"], out contentDisposition) ? contentDisposition.FileName : "place.dat"; var filePath = Path.Combine(assemblyPathInfo, fileName); // 第一步:将响应流全部读取到内存流中 using var responseStream = response.GetResponseStream(); using var memoryStream = new MemoryStream(); await responseStream.CopyToAsync(memoryStream); // 第二步:重置游标写入本地文件 memoryStream.Position = 0; using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None); await memoryStream.CopyToAsync(fileStream); // 第三步:再次重置游标,反序列化为指定业务模型 memoryStream.Position = 0; // 示例使用System.Text.Json反序列化,可替换为你项目中实际用的序列化组件 var businessModel = await JsonSerializer.DeserializeAsync<YourBusinessModel>(memoryStream); return businessModel; } catch(Exception ex) { logger.Error(ex); return default; } }
将代码中的YourBusinessModel替换为你实际的业务模型类即可。
注意事项
- 每次读取
MemoryStream前必须将Position属性设置为0,重置游标到流的起始位置,否则会读取到空内容或者不完整内容 - 如果接口返回的响应体体积过大(超过100MB),使用
MemoryStream会占用较多内存,这种场景下可以选择边写入文件边分段解析响应内容,避免内存占用过高 - 上述方案兼容你原有写入本地文件的逻辑,不需要调整原有文件存储的相关配置
内容的提问来源于stack exchange,提问作者Wojciech Szabowicz
相关产品推荐
相关产品推荐

