我有一个MVC应用程序,我试图让用户有机会下载文件的zip文件,但不成功。让我进一步解释。
在我的视图中( ImageViewer.cshtml )我有一个带有点击事件的div类,按下时我调用控制器方法( ImageViewerController.GetZipPhotos )处理下载zip文件。见下文:
div class="text" onclick="GetZipPhotos()">Download</div>
和被调用的Javascript是这样的:
function GetZipPhotos() {
$.ajax({
url: '@Url.Action("GetZipPhotos", "ImageViewer",Request.Url.Scheme)',
type: 'POST',
contentType: 'application/zip',
error: function () {
alert('There was an error!'+result);
}
});
}
现在,在我的ImageViewerController中,我有以下方法:
[HttpPost]
public ActionResult GetZipPhotos()
{
ZipResult newZipResult=new ZipResult(
Server.MapPath("~/File1.txt"),
Server.MapPath("~/File2.txt")
);
newZipResult.OutPutZipFileName = "PhotosZip.zip";
return newZipResult;
}
并且ZipResult自定义操作的声明是:
public class ZipResult:ActionResult
{
private IEnumerable<string> _filesToZip;
private string _outPutZipFileName="ZipFile.zip";
public ZipResult(params string[] filesToZip)
{
this._filesToZip = filesToZip;
}
public override void ExecuteResult(ControllerContext context)
{
using (ZipFile oneZipFile = new ZipFile()) {
oneZipFile.AddFiles(_filesToZip);
context.HttpContext.Response.ContentType = "application/zip";
context.HttpContext.Response.AppendHeader("content-disposition", "attachment; filename=" + _outPutZipFileName);
oneZipFile.Save(context.HttpContext.Response.OutputStream);
}
}
}
问题是因为调用控制器的视图名称与实际方法(GetZipPhotos)不同,因此代码不起作用。视图的名称是ImageViewer.cshtml,控制器的名称是ImageViewerController。 正如我所理解的那样,MVC框架使用代码约定,因此它希望方法的名称与视图相同。问题是我的视图和方法是不同的,因此响应永远不会回到视图。 我想创建一个基本上没有任何内容的新视图,只是从方法中调用它并返回zip文件。如果这可能是一个可能的解决方案,我怎么能从动作结果告诉哪个视图发送响应吗
答案 0 :(得分:1)
无需使用ajax进行文件下载。浏览器通常会开始下载并让您保持同一页面。此外,无需自定义操作结果,您只需使用FileResult
即可。尝试这样的事情:
public FileResult GetZipPhotos()
{
var filesToZip = new List<string> { Server.MapPath("~/File1.txt"), Server.MapPath("~/File2.txt") };
var oneZipFile = new ZipFile();
oneZipFile.AddFiles(filesToZip);
return File(oneZipFile.ToByteArray(), "application/zip", "PhotosZip.zip");
}
当然,您需要弄清楚这部分oneZipFile.ToByteArray()
,但ZipFile
类可能已经有类似的东西。
答案 1 :(得分:1)
您的ajax调用正在将响应重定向到无处。
我会这样做:
使用隐藏的iframe,将其src更改为函数中所需的路径,它应该提示文件对话框。