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");