将 ZipArchive 与 ASP.NET Core Web Api 结合使用
Using ZipArchive with ASP.NET Core Web Api
问题是如何使用 ASP.NET Core 2(当前)Web API 即时创建压缩文件夹?
我正在使用 System.IO.Compression.ZipArchive
我有几篇博文都是使用流或字节数组完成的,它们都给我相同的输出。
我可以下载 zip 文件夹,但无法打开它。
压缩后的文件夹大小正确。虽然打不开
我希望它的工作方式是让用户单击运行此操作的按钮和 return 包含一个或多个文件的压缩文件夹。
[HttpGet]
[Route("/api/download/zip")]
public async Task<IActionResult> Zip()
{
byte[] bytes = null;
using (MemoryStream zipStream = new MemoryStream())
using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");
// Running just this line gives me the zipped folder (empty) which I can open
ZipArchiveEntry entry = zip.CreateEntry("File1.pdf", CompressionLevel.Fastest);
// Adding this 2nd section will download the zip but will not open the zip folder
using (Stream stream = entry.Open())
using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read))
{
await fs.CopyToAsync(stream);
}
bytes = zipStream.ToArray();
}
return File(bytes, MediaTypeNames.Application.Zip, $"Attachments{DateTime.Now.ToBinary()}.zip");
}
任何人都可以发现错误或提出替代解决方案吗?
在处理存档之前,所有数据都不会写入流。因此在这种情况下,如果存档尚未刷新,则流中的数据可能不完整。
memoryStream.ToArray
在存档有机会将其所有数据刷新到基础流之前被调用。
考虑重构为
//...
var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");
using (MemoryStream zipStream = new MemoryStream()) {
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true)) {
ZipArchiveEntry entry = archive.CreateEntry("File1.pdf", CompressionLevel.Fastest);
using (Stream stream = entry.Open())
using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read)) {
await fs.CopyToAsync(stream);
}
}// disposal of archive will force data to be written to memory stream.
zipStream.Position = 0; //reset memory stream position.
bytes = zipStream.ToArray(); //get all flushed data
}
//...
您的示例中的假设也是打开的 FileStream
是创建条目的正确文件类型; 单个 PDF 文件。否则考虑从 tempFileName
.
中提取名称
您必须为要添加到存档的每个项目添加一个唯一的条目(文件路径)。
问题是如何使用 ASP.NET Core 2(当前)Web API 即时创建压缩文件夹?
我正在使用 System.IO.Compression.ZipArchive
我有几篇博文都是使用流或字节数组完成的,它们都给我相同的输出。
我可以下载 zip 文件夹,但无法打开它。
压缩后的文件夹大小正确。虽然打不开
我希望它的工作方式是让用户单击运行此操作的按钮和 return 包含一个或多个文件的压缩文件夹。
[HttpGet]
[Route("/api/download/zip")]
public async Task<IActionResult> Zip()
{
byte[] bytes = null;
using (MemoryStream zipStream = new MemoryStream())
using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");
// Running just this line gives me the zipped folder (empty) which I can open
ZipArchiveEntry entry = zip.CreateEntry("File1.pdf", CompressionLevel.Fastest);
// Adding this 2nd section will download the zip but will not open the zip folder
using (Stream stream = entry.Open())
using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read))
{
await fs.CopyToAsync(stream);
}
bytes = zipStream.ToArray();
}
return File(bytes, MediaTypeNames.Application.Zip, $"Attachments{DateTime.Now.ToBinary()}.zip");
}
任何人都可以发现错误或提出替代解决方案吗?
在处理存档之前,所有数据都不会写入流。因此在这种情况下,如果存档尚未刷新,则流中的数据可能不完整。
memoryStream.ToArray
在存档有机会将其所有数据刷新到基础流之前被调用。
考虑重构为
//...
var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");
using (MemoryStream zipStream = new MemoryStream()) {
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true)) {
ZipArchiveEntry entry = archive.CreateEntry("File1.pdf", CompressionLevel.Fastest);
using (Stream stream = entry.Open())
using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read)) {
await fs.CopyToAsync(stream);
}
}// disposal of archive will force data to be written to memory stream.
zipStream.Position = 0; //reset memory stream position.
bytes = zipStream.ToArray(); //get all flushed data
}
//...
您的示例中的假设也是打开的 FileStream
是创建条目的正确文件类型; 单个 PDF 文件。否则考虑从 tempFileName
.
您必须为要添加到存档的每个项目添加一个唯一的条目(文件路径)。