So i am trying to create a zip archive and return it from my web api. The controller is called from an angular 2 site. Currently the zip file is created but when i open it i get an invalid message. Originally i had the streams in using statements but had to change that as they were being disposed before the request had completed.
What i need is to create the zip file, add the csv file to its content. And then return the zip file. But the zip file is always invalid. I have read the zip archive needs to be disposed in order for it write its contents, however im not sure what is the best way to implement this. Thank you for any guidance.
public async Task<IHttpActionResult> ExportReport(int id, ReportModel report)
{
try
{
var result = await ReportGenerationService.ExportReportForId(id, report.Page, report.PageSize, report.SortField, report.SortDir, report.SearchTerm, report.StartDate, report.EndDate, report.UserId, report.TeamId, report.SelectedDateItem);
if (result != null)
{
var compressedFileStream = new MemoryStream();
var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false);
var zipEntry = zipArchive.CreateEntry("textExport.csv");
var origionalFileSteam = new MemoryStream(result.ExportToBytes());
var zipEntryStream = zipEntry.Open();
origionalFileSteam.CopyTo(zipEntryStream);
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(compressedFileStream)};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Export.zip"
};
var t = compressedFileStream.CanRead;
return ResponseMessage(response);
}
return NotFound();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
In Response to using statements:
At one point i had everything wrapped in using statements but the response would fail because the stream had already been disposed. You can see this below.
public async Task<IHttpActionResult> ExportReport(int id, ReportModel report)
{
try
{
var result = await ReportGenerationService.ExportReportForId(id, report.Page, report.PageSize, report.SortField, report.SortDir, report.SearchTerm, report.StartDate, report.EndDate, report.UserId, report.TeamId, report.SelectedDateItem);
if (result != null)
{
var compressedFileStream = new MemoryStream();
var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false);
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry("textExport.csv");
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(result.ExportToBytes()))
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
compressedFileStream.Position = 0;
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(compressedFileStream)};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Export.zip"
};
return ResponseMessage(response);
}
return NotFound();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
You are missing a handful of using(){}
blocks.
Make sure you close the originalFileSteam, zipEntryStream and the zipArchive in the proper order.
And just to be sure, reset the memoryStream. I don't know if this is needed but it won't hurt.
//using (var compressedFileStream = new MemoryStream())
var compressedFileStream = new MemoryStream();
using (var zipArchive = new ZipArchive(...))
{
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry("textExport.csv");
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(result.ExportToBytes()))
using (var zipEntryStream = zipEntry.Open())
{
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
//compressedFileStream .Position = 0;
var responseBytes =new MemoryStream(compressedFileStream.ToArray());
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(responseBytes )};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return ResponseMessage(response);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With