DotNetZip 在传入内存流时创建 0kb 文件
DotNetZip creates 0kb files when passing in memory stream
我有一个 Razor 页面,我想生成一个包含多个 CSV 文件的 Zip 文件。
当我只想生成一个文件时,它工作正常,例如
public async Task<FileStreamResult> OnGet(int id)
{
var bankDetails = _paymentFileGenerator.GeneratePaymentFiles(id);
await using var memoryStream = new MemoryStream();
await using var streamWriter = new StreamWriter(memoryStream);
await using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture)
{
Configuration = { HasHeaderRecord = false, }
};
csvWriter.WriteRecords(bankDetails);
streamWriter.Flush();
return new FileStreamResult(new MemoryStream(memoryStream.ToArray()), new MediaTypeHeaderValue("text/csv"))
{
FileDownloadName = "bacs.csv"
};
}
但是当我尝试将两个文件的内存流传递到 DotNetZip 流时,zip 下载到浏览器,但两个文件都是 0kb。关于为什么的任何想法?
public async Task<FileStreamResult> OnGet(int id)
{
var bankFiles = _paymentFileGenerator.GeneratePaymentFiles(id);
using var zipStream = new MemoryStream();
using var zip = new ZipFile();
await using var bankFileStream = new MemoryStream();
await using var bankFileStreamWriter = new StreamWriter(bankFileStream);
await using var bankFileCsvWriter = new CsvWriter(bankFileStreamWriter, CultureInfo.InvariantCulture)
{
Configuration = { HasHeaderRecord = false, }
};
bankFileCsvWriter.WriteRecords(bankFiles.BankFile);
bankFileCsvWriter.Flush();
bankFileStream.Seek(0, SeekOrigin.Begin);
zip.AddEntry("bacs.csv", (name, stream) => bankFileStream.ToArray());
await using var internalFileStream = new MemoryStream();
await using var internalFileStreamWriter = new StreamWriter(internalFileStream);
await using var internalFileCsvWriter = new CsvWriter(internalFileStreamWriter, CultureInfo.InvariantCulture);
internalFileCsvWriter.WriteRecords(bankFiles.InternalFile);
internalFileCsvWriter.Flush();
internalFileStream.Seek(0, SeekOrigin.Begin);
zip.AddEntry("internal.csv", (name, stream) => internalFileStream.ToArray());
zip.Save(zipStream);
zipStream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(new MemoryStream(zipStream.ToArray()), new MediaTypeHeaderValue("application/zip"))
{
FileDownloadName = "paymentbatch.zip"
};
}
我看过其他 Whosebug 帖子,其中有人建议添加 Seek() 函数来重置流的位置,但无论是否存在,它对我都不起作用。
调试时,当我调用 zip.AddEntry() 时,我可以看到 'bankfileStream' 流中有字节,但当我调用 zip.Save( 时,zipStream 显示 0 字节压缩流)。
任何建议表示赞赏!
我尝试了很多不同的选项,但在我改用 SharpZipLib 库之前没有任何效果。这是完整的解决方案:
public async Task<FileStreamResult> OnGet(int id)
{
var bankFiles = _paymentFileGenerator.GeneratePaymentFiles(id);
var bankFileBytes = await GetCsvFileBytes(bankFiles.BankFile, includeHeader: false);
var internalFileBytes = await GetCsvFileBytes(bankFiles.InternalFile);
var files = new List<AttachedFile>
{
new AttachedFile("bacs.csv", bankFileBytes),
new AttachedFile("internal.csv", internalFileBytes)
};
var zipStream = AddFilesToZip(files);
return new FileStreamResult(zipStream, new MediaTypeHeaderValue("application/zip"))
{
FileDownloadName = "paymentbatch.zip"
};
}
public MemoryStream AddFilesToZip(List<AttachedFile> attachedFiles)
{
var outputMemStream = new MemoryStream();
using (var zipStream = new ZipOutputStream(outputMemStream))
{
// 0-9, 9 being the highest level of compression
zipStream.SetLevel(3);
foreach (var file in attachedFiles)
{
var newEntry = new ZipEntry(file.Name) {DateTime = DateTime.Now};
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(new MemoryStream(file.Bytes), zipStream, new byte[4096]);
}
zipStream.CloseEntry();
// Stop ZipStream.Dispose() from also Closing the underlying stream.
zipStream.IsStreamOwner = false;
}
outputMemStream.Position = 0;
return outputMemStream;
}
private static async Task<byte[]> GetCsvFileBytes<T>(List<T> records, bool includeHeader = true) where T : class
{
await using var bankFileStream = new MemoryStream();
await using var bankFileStreamWriter = new StreamWriter(bankFileStream);
await using var bankFileCsvWriter = new CsvWriter(bankFileStreamWriter, CultureInfo.InvariantCulture)
{
Configuration = {HasHeaderRecord = includeHeader}
};
bankFileCsvWriter.WriteRecords(records);
bankFileStreamWriter.Flush();
return bankFileStream.ToArray();
}
public class AttachedFile
{
public byte[] Bytes { get; set; }
public string Name { get; set; }
public AttachedFile(string name, byte[] bytes)
{
Bytes = bytes;
Name = name;
}
}
我有一个 Razor 页面,我想生成一个包含多个 CSV 文件的 Zip 文件。
当我只想生成一个文件时,它工作正常,例如
public async Task<FileStreamResult> OnGet(int id)
{
var bankDetails = _paymentFileGenerator.GeneratePaymentFiles(id);
await using var memoryStream = new MemoryStream();
await using var streamWriter = new StreamWriter(memoryStream);
await using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture)
{
Configuration = { HasHeaderRecord = false, }
};
csvWriter.WriteRecords(bankDetails);
streamWriter.Flush();
return new FileStreamResult(new MemoryStream(memoryStream.ToArray()), new MediaTypeHeaderValue("text/csv"))
{
FileDownloadName = "bacs.csv"
};
}
但是当我尝试将两个文件的内存流传递到 DotNetZip 流时,zip 下载到浏览器,但两个文件都是 0kb。关于为什么的任何想法?
public async Task<FileStreamResult> OnGet(int id)
{
var bankFiles = _paymentFileGenerator.GeneratePaymentFiles(id);
using var zipStream = new MemoryStream();
using var zip = new ZipFile();
await using var bankFileStream = new MemoryStream();
await using var bankFileStreamWriter = new StreamWriter(bankFileStream);
await using var bankFileCsvWriter = new CsvWriter(bankFileStreamWriter, CultureInfo.InvariantCulture)
{
Configuration = { HasHeaderRecord = false, }
};
bankFileCsvWriter.WriteRecords(bankFiles.BankFile);
bankFileCsvWriter.Flush();
bankFileStream.Seek(0, SeekOrigin.Begin);
zip.AddEntry("bacs.csv", (name, stream) => bankFileStream.ToArray());
await using var internalFileStream = new MemoryStream();
await using var internalFileStreamWriter = new StreamWriter(internalFileStream);
await using var internalFileCsvWriter = new CsvWriter(internalFileStreamWriter, CultureInfo.InvariantCulture);
internalFileCsvWriter.WriteRecords(bankFiles.InternalFile);
internalFileCsvWriter.Flush();
internalFileStream.Seek(0, SeekOrigin.Begin);
zip.AddEntry("internal.csv", (name, stream) => internalFileStream.ToArray());
zip.Save(zipStream);
zipStream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(new MemoryStream(zipStream.ToArray()), new MediaTypeHeaderValue("application/zip"))
{
FileDownloadName = "paymentbatch.zip"
};
}
我看过其他 Whosebug 帖子,其中有人建议添加 Seek() 函数来重置流的位置,但无论是否存在,它对我都不起作用。
调试时,当我调用 zip.AddEntry() 时,我可以看到 'bankfileStream' 流中有字节,但当我调用 zip.Save( 时,zipStream 显示 0 字节压缩流)。
任何建议表示赞赏!
我尝试了很多不同的选项,但在我改用 SharpZipLib 库之前没有任何效果。这是完整的解决方案:
public async Task<FileStreamResult> OnGet(int id)
{
var bankFiles = _paymentFileGenerator.GeneratePaymentFiles(id);
var bankFileBytes = await GetCsvFileBytes(bankFiles.BankFile, includeHeader: false);
var internalFileBytes = await GetCsvFileBytes(bankFiles.InternalFile);
var files = new List<AttachedFile>
{
new AttachedFile("bacs.csv", bankFileBytes),
new AttachedFile("internal.csv", internalFileBytes)
};
var zipStream = AddFilesToZip(files);
return new FileStreamResult(zipStream, new MediaTypeHeaderValue("application/zip"))
{
FileDownloadName = "paymentbatch.zip"
};
}
public MemoryStream AddFilesToZip(List<AttachedFile> attachedFiles)
{
var outputMemStream = new MemoryStream();
using (var zipStream = new ZipOutputStream(outputMemStream))
{
// 0-9, 9 being the highest level of compression
zipStream.SetLevel(3);
foreach (var file in attachedFiles)
{
var newEntry = new ZipEntry(file.Name) {DateTime = DateTime.Now};
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(new MemoryStream(file.Bytes), zipStream, new byte[4096]);
}
zipStream.CloseEntry();
// Stop ZipStream.Dispose() from also Closing the underlying stream.
zipStream.IsStreamOwner = false;
}
outputMemStream.Position = 0;
return outputMemStream;
}
private static async Task<byte[]> GetCsvFileBytes<T>(List<T> records, bool includeHeader = true) where T : class
{
await using var bankFileStream = new MemoryStream();
await using var bankFileStreamWriter = new StreamWriter(bankFileStream);
await using var bankFileCsvWriter = new CsvWriter(bankFileStreamWriter, CultureInfo.InvariantCulture)
{
Configuration = {HasHeaderRecord = includeHeader}
};
bankFileCsvWriter.WriteRecords(records);
bankFileStreamWriter.Flush();
return bankFileStream.ToArray();
}
public class AttachedFile
{
public byte[] Bytes { get; set; }
public string Name { get; set; }
public AttachedFile(string name, byte[] bytes)
{
Bytes = bytes;
Name = name;
}
}