Home > Mobile >  Generated zip file with Asp.NET Core gives error Unexpected end of archive
Generated zip file with Asp.NET Core gives error Unexpected end of archive

Time:12-20

I am trying to generate zip file from files stored as byte arrays in SQL Database. I am using this code:

public async Task<IActionResult> Download(int id)
{
    var files = this.assignmentsService.GetFilesForAssignment(id).ToList();

    using var memoryStream = new MemoryStream();
    using var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

    foreach (var file in files)
    {
        var zipFile = archive.CreateEntry(file.Name);
        using var streamWriter = new StreamWriter(zipFile.Open());
        streamWriter.Write(file.Content);
    }

    return this.File(memoryStream.ToArray(), "application/zip", "Description.zip");
}

When I run it, the file is downloaded successfully and all the files are in the archive. But when I try to open one of them, I get the following error:

C:\Users\User\Downloads\Description.zip: Unexpected end of archive

CodePudding user response:

You should dispose the ZipArchive to ensure that it completes writing to the target stream. You can do that by wrapping the ZipArchive in a using block instead of using the using declaration here:

using var memoryStream = new MemoryStream();
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
    foreach (var file in files)
    {
        var zipFile = archive.CreateEntry(file.Name);
        using var streamWriter = new StreamWriter(zipFile.Open());
        streamWriter.Write(file.Content);
    }
}

return this.File(memoryStream.ToArray(), "application/zip", "Description.zip");

Note that there is also on overload of the File method that directly takes a stream. That way, you can use the using declaration for the ZipArchive while just keeping the memory stream open (the File() call will eventually dispose the stream after it has been written to the HTTP response):

var memoryStream = new MemoryStream();
using var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

foreach (var file in files)
{
    var zipFile = archive.CreateEntry(file.Name);
    using var streamWriter = new StreamWriter(zipFile.Open());
    streamWriter.Write(file.Content);
}

return File(memoryStream, "application/zip", "Description.zip");
  • Related