发送正在创建的 zip 文件
Send a zip file as it is being created
在我的网站上,当用户单击某个按钮时,必须将一堆文件压缩并发送出去。文件本身是由第三方生成的,我只有 URL。
我已经部分成功了,但是我有一些问题。
首先,如果要压缩的文件很多,服务器响应会很慢,因为它会先构建压缩文件,然后再发送。它甚至会在一段时间后崩溃(值得注意的是,我收到错误“算术运算中溢出或下溢。”)。
其次,现在只有在 zip 存档完成后才会发送文件。我希望立即开始下载。也就是说,只要用户从对话框中单击 "save",数据就会开始发送,并且会在创建 zip 文件时持续发送 "on the fly"。我在某些网站上看到过该功能,例如:http://download.muuto.com/
问题是,我不知道该怎么做。
我使用了这个问题的部分代码:Creating a dynamic zip of a bunch of URLs on the fly
从这个博客 post : http://dejanstojanovic.net/aspnet/2015/march/generate-zip-file-on-the-fly-in-aspnet-mvc-application/
zip 文件本身是在 ASP.NET MVC 控制器方法中创建和返回的。这是我的代码:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class MyController : Controller
{
public ActionResult DownloadFiles()
{
var files = SomeFunction();
byte[] buffer = new byte[4096];
var baseOutputStream = new MemoryStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(baseOutputStream);
zipOutputStream.SetLevel(0); //0-9, 9 being the highest level of compression
zipOutputStream.UseZip64 = UseZip64.Off;
zipOutputStream.IsStreamOwner = false;
foreach (var file in files)
{
using (WebClient wc = new WebClient())
{
// We open the download stream of the file
using (Stream wcStream = wc.OpenRead(file.Url))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName));
zipOutputStream.PutNextEntry(entry);
// As we read the stream, we add its content to the new zip entry
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
}
}
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
// Set position to 0 so that cient start reading of the stream from the begining
baseOutputStream.Position = 0;
// Set custom headers to force browser to download the file instad of trying to open it
return new FileStreamResult(baseOutputStream, "application/x-zip-compressed")
{
FileDownloadName = "Archive.zip"
};
}
}
}
好的,通过稍微调整一下响应输出流和缓冲,我找到了解决方案:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class MyController : Controller
{
public ActionResult DownloadFiles()
{
var files = SomeFunction();
// Disable Buffer Output to start the download immediately
Response.BufferOutput = false;
// Set custom headers to force browser to download the file instad of trying to open it
Response.ContentType = "application/x-zip-compressed";
Response.AppendHeader("content-disposition", "attachment; filename=Archive.zip");
byte[] buffer = new byte[4096];
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(0); // No compression
zipOutputStream.UseZip64 = UseZip64.Off;
zipOutputStream.IsStreamOwner = false;
try
{
foreach (var file in files)
{
using (WebClient wc = new WebClient())
{
// We open the download stream of the image
using (Stream wcStream = wc.OpenRead(file.Url))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName));
zipOutputStream.PutNextEntry(entry);
// As we read the stream, we add its content to the new zip entry
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
}
}
}
}
}
finally
{
zipOutputStream.Finish();
zipOutputStream.Close();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
}
}
在我的网站上,当用户单击某个按钮时,必须将一堆文件压缩并发送出去。文件本身是由第三方生成的,我只有 URL。 我已经部分成功了,但是我有一些问题。
首先,如果要压缩的文件很多,服务器响应会很慢,因为它会先构建压缩文件,然后再发送。它甚至会在一段时间后崩溃(值得注意的是,我收到错误“算术运算中溢出或下溢。”)。
其次,现在只有在 zip 存档完成后才会发送文件。我希望立即开始下载。也就是说,只要用户从对话框中单击 "save",数据就会开始发送,并且会在创建 zip 文件时持续发送 "on the fly"。我在某些网站上看到过该功能,例如:http://download.muuto.com/
问题是,我不知道该怎么做。
我使用了这个问题的部分代码:Creating a dynamic zip of a bunch of URLs on the fly 从这个博客 post : http://dejanstojanovic.net/aspnet/2015/march/generate-zip-file-on-the-fly-in-aspnet-mvc-application/
zip 文件本身是在 ASP.NET MVC 控制器方法中创建和返回的。这是我的代码:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class MyController : Controller
{
public ActionResult DownloadFiles()
{
var files = SomeFunction();
byte[] buffer = new byte[4096];
var baseOutputStream = new MemoryStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(baseOutputStream);
zipOutputStream.SetLevel(0); //0-9, 9 being the highest level of compression
zipOutputStream.UseZip64 = UseZip64.Off;
zipOutputStream.IsStreamOwner = false;
foreach (var file in files)
{
using (WebClient wc = new WebClient())
{
// We open the download stream of the file
using (Stream wcStream = wc.OpenRead(file.Url))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName));
zipOutputStream.PutNextEntry(entry);
// As we read the stream, we add its content to the new zip entry
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
}
}
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
// Set position to 0 so that cient start reading of the stream from the begining
baseOutputStream.Position = 0;
// Set custom headers to force browser to download the file instad of trying to open it
return new FileStreamResult(baseOutputStream, "application/x-zip-compressed")
{
FileDownloadName = "Archive.zip"
};
}
}
}
好的,通过稍微调整一下响应输出流和缓冲,我找到了解决方案:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class MyController : Controller
{
public ActionResult DownloadFiles()
{
var files = SomeFunction();
// Disable Buffer Output to start the download immediately
Response.BufferOutput = false;
// Set custom headers to force browser to download the file instad of trying to open it
Response.ContentType = "application/x-zip-compressed";
Response.AppendHeader("content-disposition", "attachment; filename=Archive.zip");
byte[] buffer = new byte[4096];
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(0); // No compression
zipOutputStream.UseZip64 = UseZip64.Off;
zipOutputStream.IsStreamOwner = false;
try
{
foreach (var file in files)
{
using (WebClient wc = new WebClient())
{
// We open the download stream of the image
using (Stream wcStream = wc.OpenRead(file.Url))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName));
zipOutputStream.PutNextEntry(entry);
// As we read the stream, we add its content to the new zip entry
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
}
}
}
}
}
finally
{
zipOutputStream.Finish();
zipOutputStream.Close();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
}
}