I am working on a application that has a button, when that button is clicked it calls a web api GET method. This method takes files and creates a zip folder using System.IO.Compression. This part works great. I see the folder it creates and I am able to open / extract that folder with its files. The problem i have is when the file gets returned to the browser and the browser downloads the file I get the following error: " The Compressed (zipped) folder '...pathToTheDownloadedFile.zip' is invalid. I don't understand what I am doing wrong. All other non-zipped files download and open fine.
Here is my web api GET method:
[HttpGet]
[Route("api/OrderManager/ExtractAllDocuments/{orderNum}/{mappingId}/")]
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
try
{
var docPath = @"" + HttpContext.Current.Server.MapPath("MyPath");
var files = Directory.GetFiles(docPath);
string zipName = @"supportingdocuments_order" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
//At this point the directory is created and saved as it should be
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
var fullZipPath = docPath + zipName;
byte[] bytes = File.ReadAllBytes(fullZipPath);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentLength = bytes.LongLength;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(MimeMapping.GetMimeMapping(zipName));
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
Here is my $.ajax call:
$.ajax({
url: 'myApiUrl',
method: 'GET'
}).done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '';
// get the file name from the content disposition
var disposition = xmlHeaderRequest.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
// Blob download logic taken from: https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007" and "Access Denied" error.
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
}).fail(function (data) {
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},
{
// settings
type: 'danger',
placement: {
from: "top",
align: "left"
},
delay: 2500,
z_index: 10031
});
});
I'm at a total and complete loss on this one. Thank you in advance for any help you can provide as it is greatly appreciated.