WebAPI + OWIN:直接将文件压缩到输出流不能按预期工作

时间:2018-03-08 15:40:47

标签: c# asp.net-mvc asp.net-web-api owin

我正在使用ASP.NET MVC 5 + Web API开发一个网站。其中一个要求是用户必须能够下载一个即时创建的大型zip文件。 因为我立即想要显示用户的进度,我的想法是在共振中使用带有回调的PushStreamContent。回调创建zipfile并将其流式传输到响应。

当我按照以下方式实现它时,从一个空的ASP.NET MVC + Web API项目开始,它按预期工作。一旦结果返回给客户端,就会调用回调 zipfile将流式传输到客户端。因此,一旦回调创建了zip存档并向其添加文件,用户就可以看到进度。

[RoutePrefix("api/download")]
public class DownloadController : ApiController
{
    [HttpGet]
    public HttpResponseMessage Get()
    {
        var files = new DirectoryInfo(@"c:\tempinput").GetFiles();

        var pushStreamContent = new PushStreamContent(async (outputStream, httpContext, transportContext) =>
        {
            using (var zipOutputStream = new ZipOutputStream(outputStream))
            {
                zipOutputStream.CompressionLevel = CompressionLevel.BestCompression;

                foreach (var file in files)
                {
                    zipOutputStream.PutNextEntry(file.Name);

                    using (var stream = File.OpenRead(file.FullName))
                    {
                        await stream.CopyToAsync(zipOutputStream);
                    }
                }
            }
        });

        var response = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = pushStreamContent
        };

        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        response.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment") {FileName = "MyZipfile.zip"};

        return response;
    }    
}

现在,我必须将其集成到现有网站中,该网站配置为使用Microsoft.Owin.OwinMiddleware。我使用了与上面粘贴的相同的代码,但现在行为是不同的:在创建zip文件期间,它不会流式传输到响应,而是仅在zip的创建完成时下载。因此,用户在创建文件期间看不到任何进展。

我还在我的Web API + Owin项目中尝试了不同的方法,如下所述:(generate a Zip file from azure blob storage files)。 在一个空的Asp.NET MVC项目(没有OWIN中间件)中,这完全符合预期,但是当涉及到OWIN时,我得到了这个HTTPException和stacktrace:

System.Web.HttpException:'在发送HTTP标头后,服务器无法设置状态。'

  

System.Web.dll!System.Web.HttpResponse.StatusCode.set(int value)未知       System.Web.dll!System.Web.HttpResponseWrapper.StatusCode.set(int value)未知       Microsoft.Owin.Host.SystemWeb.dll!Microsoft.Owin.Host.SystemWeb.OwinCallContext.Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.IPropertySource.SetResponseStatusCode(int value)Unknown

似乎OWIN想要设置响应状态,尽管这已经在我的Get()方法中完成(HttpResponseMessage(HttpStatusCode.OK))。

有关如何解决此问题的建议或针对不同方法的想法吗?

非常感谢!

0 个答案:

没有答案