I'm failing to generate a zip file within a web api controller. I need to generate a zip file when the method is called that can be downloaded. The zip file is purely for downloading. The zip file should not exist on the server. The contents of the zip file is an array of pdf files that exist on the server. I've attempted the following but I'm not sure how to populate the HttpResponseMessage Content object correctly.
Can anyone suggest how this is done please?
Thank you
My failing attempt
using (FileStream zipFile = new FileStream("??", FileMode.Create))
{
using (ZipArchive archive = new ZipArchive((zipFile, ZipArchiveMode.Create))
{
foreach (var pFile in listOfPdfFilenames)
{
var filePath = _pdfPathProvider.GetFullPath(pFile);
if (File.Exists(filePath))
{
archive.CreateEntryFromFile(filePath, filePath);
}
}
var result = new HttpResponseMessage(HttpStatusCode.OK);
// Not sure how to populate the content object with my zipped file
result.Content = new Content(..); // Or ByteArrayContent(..)
return result;
}
Having looked at the example provided in question #45172328 I get the "zip file is empty". I've provided an example below after this change.
Second attempt
var model = new List<FileModel>();
foreach (var pFile in listOfPdfFilenames)
{
var filePath = _pdfPathProvider.GetFullPath(pFile);
if (File.Exists(filePath))
{
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
model.Add(new FileModel
{
FileName = filePath,
FileContent = ReadToEnd(stream)
});
}
var archiveStream = model.Compress();
var content = new StreamContent(archiveStream);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = content;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "fileexport.zip"
};
return response;
Implementation for ReadToEnd method
public static byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = 0;
if (stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if (stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}
Empty zip file message