Skip to content

Unable to stream Zip File in controller's Response.Body #731

@roddone

Description

@roddone

Steps to reproduce

  1. Create a project targeting .net 3.1 or higher
  2. create a zip using new ZipOutputStream(context.Response.Body) and PutNextEntryAsync()

Expected behavior

the zip file can be sent streamingly to the client by writing directily to context.Response.Body, without creating an intermediary MemoryStream.
The reason for not using a MemoryStream and writing directly to context.Response.Bodyis to prevent high memory consumption on the server when creating big zip files. I haven't found any library that can handle this correctly, except SharpZipLib which seems to be really closed to achieve this 😥

Actual behavior

when calling stream.PutNextEntryAsync(), a "System.NotSupportedException: Specified method is not supported" is thrown., complete stacktrace :

System.NotSupportedException: Specified method is not supported.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.get_Position()
   at ICSharpCode.SharpZipLib.Zip.ZipOutputStream.<>c__DisplayClass28_0.<PutNextEntryAsync>b__0(Stream s) in C:\Users\roddone\Source\Repos\SharpZipLib\src\ICSharpCode.SharpZipLib\Zip\ZipOutputStream.cs:line 526
   at ICSharpCode.SharpZipLib.Core.StreamUtils.WriteProcToStreamAsync(Stream targetStream, MemoryStream bufferStream, Action`1 writeProc, CancellationToken ct) in C:\Users\roddone\Source\Repos\SharpZipLib\src\ICSharpCode.SharpZipLib\Core\StreamUtils.cs:line 281
   at ICSharpCode.SharpZipLib.Core.StreamUtils.WriteProcToStreamAsync(Stream targetStream, Action`1 writeProc, CancellationToken ct) in C:\Users\roddone\Source\Repos\SharpZipLib\src\ICSharpCode.SharpZipLib\Core\StreamUtils.cs:line 291
   at ICSharpCode.SharpZipLib.Zip.ZipOutputStream.PutNextEntryAsync(ZipEntry entry, CancellationToken ct) in C:\Users\roddone\Source\Repos\SharpZipLib\src\ICSharpCode.SharpZipLib\Zip\ZipOutputStream.cs:line 524
   at Program.<>c.<<<Main>$>b__0_0>d.MoveNext() in C:\Users\roddone\Source\Repos\SharpZipLib\TestStreaming\Program.cs:line 12
--- End of stack trace from previous location ---
   at Program.<>c.<<<Main>$>b__0_0>d.MoveNext() in C:\Users\roddone\Source\Repos\SharpZipLib\TestStreaming\Program.cs:line 19
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Version of SharpZipLib

Obtained from (only keep the relevant lines)

  • Compiled from source, latest commit from master

full sample to reproduce (must create a .net 6 project) :

using ICSharpCode.SharpZipLib.Zip;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", async (HttpContext context) =>
{
	await using (var stream = new ZipOutputStream(context.Response.Body))
	{
		//add file without compression
		await stream.PutNextEntryAsync(new ZipEntry("test.txt") { CompressionMethod = CompressionMethod.Stored });

		var bytes = Encoding.UTF8.GetBytes("ah ah !");
		await stream.WriteAsync(bytes);

		await stream.FinishAsync(CancellationToken.None);

	}
});

app.Run();

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzipRelated to ZIP file format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions