Writing to ZipArchive using the HttpContext OutputStream

前端 未结 5 1081
小鲜肉
小鲜肉 2020-12-01 10:05

I\'ve been trying to get the \"new\" ZipArchive included in .NET 4.5 (System.IO.Compression.ZipArchive) to work in a ASP.NET site. But it seems like it doesn\'t

5条回答
  •  无人及你
    2020-12-01 10:47

    Presumably this is not an MVC app, where you could easily just use the FileStreamResult class.

    I'm using this currently with ZipArchive created using a MemoryStream, so I know it works.

    With that in mind, have a look at the FileStreamResult.WriteFile() method:

    protected override void WriteFile(HttpResponseBase response)
    {
        // grab chunks of data and write to the output stream
        Stream outputStream = response.OutputStream;
        using (FileStream)
        {
            byte[] buffer = newbyte[_bufferSize];
            while (true)
            {
                int bytesRead = FileStream.Read(buffer, 0, _bufferSize);
                if (bytesRead == 0)
                {
                    // no more data
                    break;
                }
                outputStream.Write(buffer, 0, bytesRead);
            }
        }
    }
    

    (Entire FileStreamResult on CodePlex)

    Here is how I'm generating and returning the ZipArchive.
    You should have no issues replacing the FSR with the guts of the WriteFile method from above, where FileStream becomes resultStream from the code below:

    var resultStream = new MemoryStream();
    
    using (var zipArchive = new ZipArchive(resultStream, ZipArchiveMode.Create, true))
    {
        foreach (var doc in req)
        {
            var fileName = string.Format("Install.Rollback.{0}.v{1}.docx", doc.AppName, doc.Version);
            var xmlData = doc.GetXDocument();
            var fileStream = WriteWord.BuildFile(templatePath, xmlData);
    
            var docZipEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
            using (var entryStream = docZipEntry.Open())
            {
                fileStream.CopyTo(entryStream);
            }
        }
    }
    resultStream.Position = 0;
    
    // add the Response Header for downloading the file
    var cd = new ContentDisposition
        {
            FileName = string.Format(
                "{0}.{1}.{2}.{3}.Install.Rollback.Documents.zip",
                DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, (long)DateTime.Now.TimeOfDay.TotalSeconds),
            // always prompt the user for downloading, set to true if you want 
            // the browser to try to show the file inline
            Inline = false,
        };
    Response.AppendHeader("Content-Disposition", cd.ToString());
    
    // stuff the zip package into a FileStreamResult
    var fsr = new FileStreamResult(resultStream, MediaTypeNames.Application.Zip);    
    return fsr;
    

    Finally, if you will be writing large streams (or a larger number of them at any given time), then you may want to consider using anonymous pipes to write the data to the output stream immediately after you write it to the underlying stream in the zip file. Because you will be holding all the file contents in memory on the server. The end of this answer to a similar question has a nice explanation of how to do that.

提交回复
热议问题