I have a server hosting a large XML file archive and an API retrieves requested files inside a zip. If I select around 11 or less files, the zip returns just fine. If I retrieve more, I receive the following error when attempting to open the zip:
"Windows cannot open the folder. The Compressed (zipped) Folder is invalid."
Here are the data classes and methods to create the zip:
//Archive file containing filename and content as memory stream
public class ArchiveFile {
public string FileName;
public System.IO.MemoryStream FileContent;
}
//Method to retrieve archive files and zip them
public static System.IO.MemoryStream GetFilesAsZip (string[] arrFileNames) {
MemoryStream zipStream = null;
using (zipStream = new MemoryStream()) {
// Retrieve files using above method
ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames);
// Initialize new ZipArchive on the return object's MemoryStream property
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) {
// Write file entries into archive
foreach (ArchiveFile dataFile in retrievedFiles) {
if (dataFile.FileContent != null) {
// Create new ZipArchiveEntry with content
ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName);
dataFile.FileContent.WriteTo(zipEntry.Open());
}//end if
} // end foreach
} //end using
} //end using
return zipStream;
}//end method
//API to return content to user as an MVC File Content Result
[HttpGet]
public ActionResult DownloadFiles (string [] fileNames) {
FileContentResult data = new FileContentResult(GetFiles(fileNames).GetBuffer(), “application/zip”) { FileDownloadName = “files.zip” };
return data;
} //end method
The corruption may have something to do with space allocation when writing to the memory stream. I noticed all my "successful" zips (11 or less files) were of size 259 KB but all "unsuccessful" zips (more than 11 files) were of size 517 KB, with some larger attempted zips of size 1034 KB. It strikes me as too much of a coincidence that these are all multiples of 258.5 KB, especially since a zip of 11 files results in a 259 KB zip but a zip of 12 files results in a 517 KB zip.
Any insight on what it could be?
ASP.Net Core API Controller returns corrupted excel file
return this in your controller
return new FileResult("demo.zip", Path.Combine(sWebRootFolder, sFileName), "application/zip");
add this code
public class FileResult : ActionResult
{
public FileResult(string fileDownloadName, string filePath, string contentType)
{
FileDownloadName = fileDownloadName;
FilePath = filePath;
ContentType = contentType;
}
public string ContentType { get; private set; }
public string FileDownloadName { get; private set; }
public string FilePath { get; private set; }
public async override Task ExecuteResultAsync(ActionContext context)
{
var response = context.HttpContext.Response;
response.ContentType = ContentType;
context.HttpContext.Response.Headers.Add("Content-Disposition", new[] { "attachment; filename=" + FileDownloadName });
using (var fileStream = new FileStream(FilePath, FileMode.Open))
{
await fileStream.CopyToAsync(context.HttpContext.Response.Body);
}
}
}
your code refactored
public byte[] GetFilesAsZip (string[] arrFileNames) {
byte[] buffer = null;
using (MemoryStream zipStream = new MemoryStream()) {
// Retrieve files using above method
ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames);
// Initialize new ZipArchive on the return object's MemoryStream property
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) {
// Write file entries into archive
foreach (ArchiveFile dataFile in retrievedFiles) {
if (dataFile.FileContent != null) {
// Create new ZipArchiveEntry with content
ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName);
dataFile.FileContent.WriteTo(zipEntry.Open());
}//end if
} // end foreach
} //end using
buffer = zipStream.ToArray();
} //end using
return buffer;
}//end method
you should be able to change this to
FileContentResult data = new FileContentResult(GetFiles(fileNames), “application/zip”) { FileDownloadName = “files.zip” };
I've had success in the past doing return File(fileLocation, "application/zip", fileName);
where fileLocation is the path to the folder and fileName is the name of the actual folder. You can do this right in your ActionResult
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.