我在我的一个 Controller 中执行了一项操作,该操作创建了一个可下载的 zip 文件,该文件应提供给用户。目前我的代码看起来像这样:
using(var memoryStream = new MemoryStream()) {
// ... use SharpZipLib to write zip file content to the above MemoryStream ...
return File(memoryStream.ToArray(), "application/zip", "file.zip");
}
我想知道将 memoryStream 转换为 byte[]
是否是个好主意,我猜这比使用流占用更多内存? File()
有一个重载,它接受一个 Stream
对象,我传入了我的 memoryStream 变量,但随后只显示了一个空白页面。
理想情况下,我不必使用 FileStream
并将文件写入磁盘。
最佳答案
如果您真的关心内存,那么这里有一个直接写入响应流的解决方案。首先定义您的自定义 ActionResult:
public class SharpZipLibResult : FileResult
{
private readonly string _fileDownloadName;
private readonly string[] _filesToZip;
private const int ChunkSize = 1024;
public SharpZipLibResult(string fileDownloadName, params string[] filesToZip)
: base("application/octet-stream")
{
_fileDownloadName = fileDownloadName;
_filesToZip = filesToZip;
}
protected override void WriteFile(HttpResponseBase response)
{
var cd = new ContentDisposition();
cd.FileName = _fileDownloadName;
response.AddHeader("Content-Disposition", cd.ToString());
response.BufferOutput = false;
using (var zipStream = new ZipOutputStream(response.OutputStream))
{
foreach (var file in _filesToZip)
{
var entry = new ZipEntry(Path.GetFileName(file));
zipStream.PutNextEntry(entry);
using (var reader = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
byte[] buffer = new byte[ChunkSize];
int bytesRead;
while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
{
byte[] actual = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, actual, 0, bytesRead);
zipStream.Write(actual, 0, actual.Length);
}
}
}
}
}
}
使用这种技术,您可以提供一些非常大的 zip 文件,而无需关心内存或不必清理服务器硬盘驱动器上的一些临时 zip 文件。
最后,您的 Controller 操作可能如下所示:
public ActionResult Index()
{
return new SharpZipLibResult(
"result.zip",
@"c:\work\report1.pdf",
@"c:\work\report2.pdf",
@"c:\work\report3.pdf"
);
}
使用此方法可最大限度地减少内存占用,因为 zip 直接写入响应流,而响应流将由底层网络套接字表示。
当然,根据文件的存储位置,SharpZipLibResult
可以进行调整。这里我假设文件存储在文件系统上。
关于c# - ASP.NET MVC : is it a good idea to return a File result from a byte[]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1687812/