Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在内存中创建Zip文件时,为什么必须解析MemoryStream才能正确创建Zip?_C#_.net - Fatal编程技术网

C# 在内存中创建Zip文件时,为什么必须解析MemoryStream才能正确创建Zip?

C# 在内存中创建Zip文件时,为什么必须解析MemoryStream才能正确创建Zip?,c#,.net,C#,.net,我在这里查看了其他问题,但是没有人回答我的问题,为什么我不能使用已经存在的MemoryStream来创建zip 下面是一个工作API方法,用于获取包含文件的压缩文件夹。服务器上已经存在这些文件,该方法只需查找这些文件的位置,然后在内存中检索所有文件,并向用户发送一个包含所有文件的压缩文件夹的HttpResponMessage对象。然而,下面有一行代码似乎没有意义。我必须将MemoryStream解析为字节数组,然后再返回MemoryStream,以便正确地创建和发送Zip。这似乎是错误的,但我不

我在这里查看了其他问题,但是没有人回答我的问题,为什么我不能使用已经存在的MemoryStream来创建zip

下面是一个工作API方法,用于获取包含文件的压缩文件夹。服务器上已经存在这些文件,该方法只需查找这些文件的位置,然后在内存中检索所有文件,并向用户发送一个包含所有文件的压缩文件夹的HttpResponMessage对象。然而,下面有一行代码似乎没有意义。我必须将MemoryStream解析为字节数组,然后再返回MemoryStream,以便正确地创建和发送Zip。这似乎是错误的,但我不知道如何纠正它。(见下文“//工作:”和“//不工作:)

公共HttpResponseMessage GetEvalByCompany([FromUri]Guid id,[FromUri]int year) { 尝试 { 字符串companyName=\u portalDB.companys.FirstOrDefault(c=>c.Id==Id).FirmName; //获取给定公司在给定年份的所有评估文件路径 var files=\u evaluationDB.Evaluations.Where(j=>j.CompanyId==id)。选择(j=>@“C:\Path\To\File”+j.RelativePath.Replace(“~”,@“)。Replace(@“/”,@“\”)。Distinct().ToList(); 使用(var outStream=new MemoryStream()) { 使用(var archive=new ZipArchive(扩展,ZipArchiveMode.Create,true)) { foreach(文件中的var记录) { var fileInArchive=archive.CreateEntryFromFile(记录,路径.GetFileName(记录),压缩级别.Optimal); } } //创建响应 HttpResponseMessage response=Request.CreateResponse(HttpStatusCode.OK); //作品: response.Content=newstreamcontent(newmemoryStream(outStream.ToArray());//为什么需要这样做? //不起作用: //response.Content=newstreamcontent(outStream);//为什么不起作用? //添加适当的标题,使浏览器将响应识别为下载 response.Content.Headers.ContentDisposition=new System.Net.Http.Headers.ContentDispositionHeaderValue(“附件”); response.Content.Headers.ContentDisposition.FileName=“公司评估-”+companyName+“.zip”; response.Content.Headers.ContentType=新系统.Net.Http.Headers.MediaTypeHeaderValue(“应用程序/zip”); 返回响应; } } 捕获(例外情况除外) { 返回ErrorHandler.HandleException(例如,请求); } } 根据我收到的答案,我能够修复代码,因此它不必不必要地解析流。以下是更新后的代码,供未来开发人员简单地寻找解决方案。删除using似乎也不会导致任何GC问题。我找到了一个链接来更好地解释这一点。()

公共HttpResponseMessage GetEvalByCompany([FromUri]Guid id,[FromUri]int year) { 尝试 { 字符串companyName=\u portalDB.companys.FirstOrDefault(c=>c.Id==Id).FirmName; //获取给定公司在给定年份的所有评估文件路径 var files=\u evaluationDB.Evaluations.Where(j=>j.CompanyId==id)。选择(j=>@“C:\Path\To\File”+j.RelativePath.Replace(“~”,@“)。Replace(@“/”,@“\”)。Distinct().ToList(); var outStream=新内存流(); 使用(var archive=new ZipArchive(扩展,ZipArchiveMode.Create,true)) { foreach(文件中的var记录) { var fileInArchive=archive.CreateEntryFromFile(记录,路径.GetFileName(记录),压缩级别.Optimal); } } //创建响应 HttpResponseMessage response=Request.CreateResponse(HttpStatusCode.OK); //更新代码 扩展。搜索(0,SeekOrigin.Begin); response.Content=newstreamcontent(outStream);//现在可以工作,因为outStream不在using块中 //添加适当的标题,使浏览器将响应识别为下载 response.Content.Headers.ContentDisposition=new System.Net.Http.Headers.ContentDispositionHeaderValue(“附件”); response.Content.Headers.ContentDisposition.FileName=“公司评估-”+companyName+“.zip”; response.Content.Headers.ContentType=新系统.Net.Http.Headers.MediaTypeHeaderValue(“应用程序/zip”); 返回响应; } 捕获(例外情况除外) { 返回ErrorHandler.HandleException(例如,请求); } }
这里的问题是,您原来的MemoryStream在使用之前就被处理掉了。StreamContent保留对已处置对象的引用。您需要删除用于扩展流的使用块,并以某种方式安排稍后处理。

删除

using (var outStream = new MemoryStream()),
只留下:

var outStream = new MemoryStream();
随后:

outStream.Seek(0, SeekOrigin.Begin)
response.Content = new StreamContent(outStream);

当我使用.seek(0,SeekOrigin.Begin)或.Position=0时,我得到的结果与“不工作”代码相同。broswer得到一个“成功”的200响应,其标题确认内容中的文档,但状态为失败且未下载zip。这很有效。使用是个问题,基于这个链接,我似乎并不真的需要它,因为流的处理似乎没有任何“现实世界的影响”。我认为任何包装在使用括号中的东西都可以使用实现的流,但在这种情况下,至少在返回时,似乎有一个警告。Upvoting,您的答案,因为它确实有助于解释问题,但ipavlu的实际代码可以使用
var outStream = new MemoryStream();
outStream.Seek(0, SeekOrigin.Begin)
response.Content = new StreamContent(outStream);