通过AJAX MVC下载Excel文件


92

我在MVC中有一个大(ish)形式。

我需要能够生成一个Excel文件,其中包含来自该表单子集的数据。

棘手的一点是,这不应影响表单的其余部分,因此我想通过AJAX进行操作。我遇到了一些关于SO的问题,这些问题似乎相关,但是我无法完全弄清楚答案的含义。

这似乎是我所追求的最接近的东西:asp-net-mvc-downloading-excel-但我不确定我是否知道响应,而且它已经存在了两年。我还遇到了另一篇有关使用iframe来处理文件下载的文章(找不到该文章了),但是我不确定如何在MVC中使用它。

如果我正在做完整的回发,但我的excel文件返回的很好,但是我无法在mvc中将其与AJAX一起使用。

Answers:


215

您不能直接通过AJAX调用返回要下载的文件,因此,另一种方法是使用AJAX调用将相关数据发布到服务器。然后,您可以使用服务器端代码来创建Excel文件(我建议为此使用EPPlus或NPOI,尽管听起来好像您正在使用此部分)。

2016年9月更新

我的原始答案(下)已经超过3年了,所以我想我会进行更新,因为通过AJAX下载文件时不再在服务器上创建文件,但是,我留下了原始答案,因为它可能仍会有所用,具体取决于您的具体要求。

在我的MVC应用程序中,常见的情况是通过网页进行报告,该网页具有一些用户配置的报告参数(日期范围,过滤器等)。当用户指定了将其发布到服务器的参数后,将生成报告(例如,将Excel文件作为输出),然后将结果文件作为字节数组TempData存储在具有唯一引用的存储桶中。该引用作为Json结果传递回我的AJAX函数,该函数随后重定向到单独的控制器操作,以从TempData最终用户浏览器提取数据并下载到最终用户浏览器。

为了提供更多细节,假设您有一个MVC View,它具有绑定到Model类的形式,让我们调用Model ReportVM

首先,需要一个控制器操作来接收发布的模型,例如:

public ActionResult PostReportPartial(ReportVM model){

   // Validate the Model is correct and contains valid data
   // Generate your report output based on the model parameters
   // This can be an Excel, PDF, Word file - whatever you need.

   // As an example lets assume we've generated an EPPlus ExcelPackage

   ExcelPackage workbook = new ExcelPackage();
   // Do something to populate your workbook

   // Generate a new unique identifier against which the file can be stored
   string handle = Guid.NewGuid().ToString();

   using(MemoryStream memoryStream = new MemoryStream()){
        workbook.SaveAs(memoryStream);
        memoryStream.Position = 0;
        TempData[handle] = memoryStream.ToArray();
   }      

   // Note we are returning a filename as well as the handle
   return new JsonResult() { 
         Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
   };

}

将我的MVC表单发布到上面的控制器并接收响应的AJAX调用如下所示:

$ajax({
    cache: false,
    url: '/Report/PostReportPartial',
    data: _form.serialize(), 
    success: function (data){
         var response = JSON.parse(data);
         window.location = '/Report/Download?fileGuid=' + response.FileGuid 
                           + '&filename=' + response.FileName;
    }
})

控制器处理文件下载的操作:

[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{   
   if(TempData[fileGuid] != null){
        byte[] data = TempData[fileGuid] as byte[];
        return File(data, "application/vnd.ms-excel", fileName);
   }   
   else{
        // Problem - Log the error, generate a blank file,
        //           redirect to another controller action - whatever fits with your application
        return new EmptyResult();
   }
}

如果需要,可以轻松进行的另一项更改是将文件的MIME类型作为第三个参数传递,以便一个Controller动作可以正确地提供多种输出文件格式。

这消除了在服务器上创建和存储任何物理文件的需要,因此不需要内务处理例程,这对最终用户也是无缝的。

请注意,使用TempData而不是使用的好处Session是,一旦TempData读取数据便将其清除,因此,如果您有大量文件请求,则在内存使用方面将更加有效。请参见TempData最佳实践

原始答案

您不能直接通过AJAX调用返回要下载的文件,因此,另一种方法是使用AJAX调用将相关数据发布到服务器。然后,您可以使用服务器端代码来创建Excel文件(我建议为此使用EPPlus或NPOI,尽管听起来好像您正在使用此部分)。

在服务器上创建文件后,将文件路径(或只是文件名)作为AJAX调用的返回值,然后将JavaScript window.location设置为此URL,这将提示浏览器下载文件。

从最终用户的角度来看,文件下载操作是无缝的,因为他们永远不会离开发出请求的页面。

下面是一个简单的ajax调用示例,以实现此目的:

$.ajax({
    type: 'POST',
    url: '/Reports/ExportMyData', 
    data: '{ "dataprop1": "test", "dataprop2" : "test2" }',
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (returnValue) {
        window.location = '/Reports/Download?file=' + returnValue;
    }
});
  • url参数是Controller / Action方法,您的代码将在其中创建Excel文件。
  • data参数包含将从表单中提取的json数据。
  • returnValue将是您新创建的Excel文件的文件名。
  • window.location的命令重定向到实际返回供下载的文件控制器/操作方法。

下载操作的示例控制器方法为:

[HttpGet]
public virtual ActionResult Download(string file)
{   
  string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file);
  return File(fullPath, "application/vnd.ms-excel", file);
}

3
这看起来是一个不错的潜在选择,但是在我继续之前,没有其他选择不涉及首先在服务器上创建文件的选择吗?
瓦卢克

4
并不是我知道-我已经成功使用了很多次这种方法。从用户的角度来看,它是无缝的,唯一要注意的是,随着时间的推移,您将需要一个整理例程来整理所创建的文件。
connectedsoftware

7
创建端点'/ Download?file = ...'会带来巨大的安全风险-我不是安全专家,但我认为您想添加用户身份验证,输入环境卫生,MVC的[ValidateAntiForgeryToken]并提及其他最佳安全性-此答案的做法。
Jimmy

2
@CSL我总是收到错误0x800a03f6-JavaScript运行时错误:var响应上的无效字符= JSON.parse(data);
立场

2
太好了,您为什么不将旧答案放在底部呢?而新的答案在最上面,这样人们就不会浪费时间
goamn

19

我的2美分-您不需要将excel作为物理文件存储在服务器上-而是将其存储在(会话)缓存中。为您的Cache变量(存储该Excel文件)使用唯一生成的名称-这将是您(初始)ajax调用的返回。这样,您就不必处理文件访问问题,不需要时管理(删除)文件等,而且将文件保存在缓存中可以更快地进行检索。


1
你到底会怎么做?听起来不错。
Natalia 2014年

2
一个例子会很好(我的意思是如何将其存储在缓存中,而不是生成excel文件)。
Tadej

可伸缩性如何?如果用户正在下载多个大型报告?
Zapnologica

如果您使用的是Azure,则会话将一直有效,直到您关闭ARRAffinity。
JeeShen Lee

14

我最近能够在MVC中完成此操作(尽管不需要使用AJAX),而无需创建物理文件,并且以为我可以共享我的代码:

超级简单的JavaScript函数(单击datatables.net按钮可触发此操作):

function getWinnersExcel(drawingId) {
    window.location = "/drawing/drawingwinnersexcel?drawingid=" + drawingId;
}

C#控制器代码:

    public FileResult DrawingWinnersExcel(int drawingId)
    {
        MemoryStream stream = new MemoryStream(); // cleaned up automatically by MVC
        List<DrawingWinner> winnerList = DrawingDataAccess.GetWinners(drawingId); // simple entity framework-based data retrieval
        ExportHelper.GetWinnersAsExcelMemoryStream(stream, winnerList, drawingId);

        string suggestedFilename = string.Format("Drawing_{0}_Winners.xlsx", drawingId);
        return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", suggestedFilename);
    }

在ExportHelper类中,我确实使用了第三方工具(GemBox.Spreadsheet)来生成Excel文件,并且该文件具有“保存到流”选项。话虽这么说,创建Excel文件的方法有很多,可以很容易地将它们写入内存流。

public static class ExportHelper
{
    internal static void GetWinnersAsExcelMemoryStream(MemoryStream stream, List<DrawingWinner> winnerList, int drawingId)
    {

        ExcelFile ef = new ExcelFile();

        // lots of excel worksheet building/formatting code here ...

        ef.SaveXlsx(stream);
        stream.Position = 0; // reset for future read

     }
}

在IE,Chrome和Firefox中,浏览器会提示您下载文件,并且不会发生实际的导航。


8

首先创建将创建Excel文件的控制器操作

[HttpPost]
public JsonResult ExportExcel()
{
    DataTable dt = DataService.GetData();
    var fileName = "Excel_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xls";

    //save the file to server temp folder
    string fullPath = Path.Combine(Server.MapPath("~/temp"), fileName);

    using (var exportData = new MemoryStream())
    {
        //I don't show the detail how to create the Excel, this is not the point of this article,
        //I just use the NPOI for Excel handler
        Utility.WriteDataTableToExcel(dt, ".xls", exportData);

        FileStream file = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
        exportData.WriteTo(file);
        file.Close();
    }

    var errorMessage = "you can return the errors in here!";

    //return the Excel file name
    return Json(new { fileName = fileName, errorMessage = "" });
}

然后创建“下载”操作

[HttpGet]
[DeleteFileAttribute] //Action Filter, it will auto delete the file after download, 
                      //I will explain it later
public ActionResult Download(string file)
{
    //get the temp folder and file path in server
    string fullPath = Path.Combine(Server.MapPath("~/temp"), file);

    //return the file for download, this is an Excel 
    //so I set the file content type to "application/vnd.ms-excel"
    return File(fullPath, "application/vnd.ms-excel", file);
}

如果要在下载后删除文件,请创建此文件

public class DeleteFileAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Flush();

        //convert the current filter context to file and get the file path
        string filePath = (filterContext.Result as FilePathResult).FileName;

        //delete the file after download
        System.IO.File.Delete(filePath);
    }
}

最后从您的MVC Razor视图进行ajax调用

//I use blockUI for loading...
$.blockUI({ message: '<h3>Please wait a moment...</h3>' });    
$.ajax({
    type: "POST",
    url: '@Url.Action("ExportExcel","YourController")', //call your controller and action
    contentType: "application/json; charset=utf-8",
    dataType: "json",
}).done(function (data) {
    //console.log(data.result);
    $.unblockUI();

    //get the file name for download
    if (data.fileName != "") {
        //use window.location.href for redirect to download action for download the file
        window.location.href = "@Url.RouteUrl(new 
            { Controller = "YourController", Action = "Download"})/?file=" + data.fileName;
    }
});

7

我使用了CSL发布的解决方案,但我建议您在整个会话过程中不要将文件数据存储在Session中。通过使用TempData,在下一个请求(该文件的GET请求)之后,文件数据将自动删除。您还可以在下载操作中管理会话中文件数据的删除。

会话可能会消耗大量内存/空间,具体取决于会话状态存储以及会话期间导出的文件数量以及用户是否很多。

我已经从CSL更新了服务端代码,改为使用TempData。

public ActionResult PostReportPartial(ReportVM model){

   // Validate the Model is correct and contains valid data
   // Generate your report output based on the model parameters
   // This can be an Excel, PDF, Word file - whatever you need.

   // As an example lets assume we've generated an EPPlus ExcelPackage

   ExcelPackage workbook = new ExcelPackage();
   // Do something to populate your workbook

   // Generate a new unique identifier against which the file can be stored
   string handle = Guid.NewGuid().ToString()

   using(MemoryStream memoryStream = new MemoryStream()){
        workbook.SaveAs(memoryStream);
        memoryStream.Position = 0;
        TempData[handle] = memoryStream.ToArray();
   }      

   // Note we are returning a filename as well as the handle
   return new JsonResult() { 
         Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
   };

}

[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{   
   if(TempData[fileGuid] != null){
        byte[] data = TempData[fileGuid] as byte[];
        return File(data, "application/vnd.ms-excel", fileName);
   }   
   else{
        // Problem - Log the error, generate a blank file,
        //           redirect to another controller action - whatever fits with your application
        return new EmptyResult();
   }
}

@Nichlas我也开始使用TempData,您的回答提示我更新我的内容以反映这一点!
connectedsoftware

5

使用ClosedXML.Excel;

   public ActionResult Downloadexcel()
    {   
        var Emplist = JsonConvert.SerializeObject(dbcontext.Employees.ToList());
        DataTable dt11 = (DataTable)JsonConvert.DeserializeObject(Emplist, (typeof(DataTable)));
        dt11.TableName = "Emptbl";
        FileContentResult robj;
        using (XLWorkbook wb = new XLWorkbook())
        {
            wb.Worksheets.Add(dt11);
            using (MemoryStream stream = new MemoryStream())
            {
                wb.SaveAs(stream);
                var bytesdata = File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "myFileName.xlsx");
                robj = bytesdata;
            }
        }


        return Json(robj, JsonRequestBehavior.AllowGet);
    }


在AJAX CALL成功模块中,成功:function(Rdata){debugger; var bytes = new Uint8Array(Rdata.FileContents); var blob = new Blob([bytes],{type:“ application / vnd.openxmlformats-officedocument.spreadsheetml.sheet”}); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download =“ myFileName.xlsx”; link.click(); }
GVKRAO

有人在上面的链接中实现了Excel文件下载,它仅适用于@ html.Beginform(),然后在进行少量更改后需要该代码,对于AJAX调用成功模块,请检查一下,它在AJAX调用中正常工作
GVKRAO

3
$ .ajax({
                类型:“ GET”,
                网址:“ / Home / Downloadexcel /”,
                contentType:“ application / json; charset = utf-8”,
                数据:空,
                成功:函数(Rdata){
                    调试器;
                    var bytes = new Uint8Array(Rdata.FileContents); 
                    var blob = new Blob([bytes],{type:“ application / vnd.openxmlformats-officedocument.spreadsheetml.sheet”});
                    var link = document.createElement('a');
                    link.href = window.URL.createObjectURL(blob);
                    link.download =“ myFileName.xlsx”;
                    link.click();
                },
                错误:函数(err){

                }

            });

1

可以接受的答案对我来说并不奏效,因为从ajax调用中得到了502 Bad Gateway结果,即使控制器似乎一切正常。

也许我正在用TempData达到极限-不确定,但是我发现如果我使用IMemoryCache而不是TempData,它可以正常工作,因此这是我接受的答案中的代码适应版本:

public ActionResult PostReportPartial(ReportVM model){

   // Validate the Model is correct and contains valid data
   // Generate your report output based on the model parameters
   // This can be an Excel, PDF, Word file - whatever you need.

   // As an example lets assume we've generated an EPPlus ExcelPackage

   ExcelPackage workbook = new ExcelPackage();
   // Do something to populate your workbook

   // Generate a new unique identifier against which the file can be stored
   string handle = Guid.NewGuid().ToString();

   using(MemoryStream memoryStream = new MemoryStream()){
        workbook.SaveAs(memoryStream);
        memoryStream.Position = 0;
        //TempData[handle] = memoryStream.ToArray();

        //This is an equivalent to tempdata, but requires manual cleanup
        _cache.Set(handle, memoryStream.ToArray(), 
                    new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(10))); 
                    //(I'd recommend you revise the expiration specifics to suit your application)

   }      

   // Note we are returning a filename as well as the handle
   return new JsonResult() { 
         Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
   };

}

AJAX呼叫仍然与接受的答案相同(我未做任何更改):

$ajax({
    cache: false,
    url: '/Report/PostReportPartial',
    data: _form.serialize(), 
    success: function (data){
         var response = JSON.parse(data);
         window.location = '/Report/Download?fileGuid=' + response.FileGuid 
                           + '&filename=' + response.FileName;
    }
})

控制器处理文件下载的操作:

[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{   
    if (_cache.Get<byte[]>(fileGuid) != null)
    {
        byte[] data = _cache.Get<byte[]>(fileGuid);
        _cache.Remove(fileGuid); //cleanup here as we don't need it in cache anymore
        return File(data, "application/vnd.ms-excel", fileName);
    }
    else
    {
        // Something has gone wrong...
        return View("Error"); // or whatever/wherever you want to return the user
    }
}

...

现在有一些额外的代码可用于设置MemoryCache ...

为了使用“ _cache”,我为控制器注入了构造函数,如下所示:

using Microsoft.Extensions.Caching.Memory;
namespace MySolution.Project.Controllers
{
 public class MyController : Controller
 {
     private readonly IMemoryCache _cache;

     public LogController(IMemoryCache cache)
     {
        _cache = cache;
     }

     //rest of controller code here
  }
 }

并确保在Startup.cs的ConfigureServices中具有以下内容:

services.AddDistributedMemoryCache();

0

该线程帮助我创建了自己的解决方案,我将在这里分享。我最初使用的是GET ajax请求,没有任何问题,但是到了超出请求URL长度的地步,所以我不得不进行POST。

javascript使用JQuery文件下载插件,并包含2个后续调用。一项POST(发送参数)和一项GET检索文件。

 function download(result) {
        $.fileDownload(uri + "?guid=" + result,
        {
            successCallback: onSuccess.bind(this),
            failCallback: onFail.bind(this)
        });
    }

    var uri = BASE_EXPORT_METADATA_URL;
    var data = createExportationData.call(this);

    $.ajax({
        url: uri,
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: download.bind(this),
        fail: onFail.bind(this)
    });

服务器端

    [HttpPost]
    public string MassExportDocuments(MassExportDocumentsInput input)
    {
        // Save query for file download use
        var guid = Guid.NewGuid();
        HttpContext.Current.Cache.Insert(guid.ToString(), input, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration);
        return guid.ToString();
    }

   [HttpGet]
    public async Task<HttpResponseMessage> MassExportDocuments([FromUri] Guid guid)
    {
        //Get params from cache, generate and return
        var model = (MassExportDocumentsInput)HttpContext.Current.Cache[guid.ToString()];
          ..... // Document generation

        // to determine when file is downloaded
        HttpContext.Current
                   .Response
                   .SetCookie(new HttpCookie("fileDownload", "true") { Path = "/" });

        return FileResult(memoryStream, "documents.zip", "application/zip");
    }

0

CSL的答案是在我正在从事的项目中实现的,但是我遇到的问题是在Azure上横向扩展,导致文件下载中断。相反,我能够通过一个AJAX调用来做到这一点:

服务器

[HttpPost]
public FileResult DownloadInvoice(int id1, int id2)
{
    //necessary to get the filename in the success of the ajax callback
    HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

    byte[] fileBytes = _service.GetInvoice(id1, id2);
    string fileName = "Invoice.xlsx";
    return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

CLIENT从ajax post下载Handle文件的修改版本)

$("#downloadInvoice").on("click", function() {
    $("#loaderInvoice").removeClass("d-none");

    var xhr = new XMLHttpRequest();
    var params = [];
    xhr.open('POST', "@Html.Raw(Url.Action("DownloadInvoice", "Controller", new { id1 = Model.Id1, id2 = Model.Id2 }))", true);
    xhr.responseType = 'arraybuffer';
    xhr.onload = function () {
        if (this.status === 200) {
            var filename = "";
            var disposition = xhr.getResponseHeader('Content-Disposition');
            if (disposition && disposition.indexOf('attachment') !== -1) {
                var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                var matches = filenameRegex.exec(disposition);
                if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
            }
            var type = xhr.getResponseHeader('Content-Type');

            var blob = typeof File === 'function'
                ? new File([this.response], filename, { type: type })
                : new Blob([this.response], { type: type });
            if (typeof window.navigator.msSaveBlob !== 'undefined') {
                // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
                window.navigator.msSaveBlob(blob, filename);
            } else {
                var URL = window.URL || window.webkitURL;
                var downloadUrl = URL.createObjectURL(blob);

                if (filename) {
                    // use HTML5 a[download] attribute to specify filename
                    var a = document.createElement("a");
                    // safari doesn't support this yet
                    if (typeof a.download === 'undefined') {
                        window.location = downloadUrl;
                    } else {
                        a.href = downloadUrl;
                        a.download = filename;
                        document.body.appendChild(a);
                        a.click();
                    }
                } else {
                    window.location = downloadUrl;

                }

                setTimeout(function() {
                        URL.revokeObjectURL(downloadUrl);
                    $("#loaderInvoice").addClass("d-none");
                }, 100); // cleanup
            }
        }
    };
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send($.param(params));
});

0
  $.ajax({
    global: false,
    url: SitePath + "/User/ExportTeamMembersInExcel",
    "data": { 'UserName': UserName, 'RoleId': RoleId, UserIds: AppraseeId },
    "type": "POST",
    "dataType": "JSON",
   "success": function (result) {
        debugger
        var bytes = new Uint8Array(result.FileContents);
        var blob = new Blob([bytes], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
        var link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = "myFileName.xlsx";
        link.click();
      },
    "error": function () {
        alert("error");
    }
})


[HttpPost]
    public JsonResult ExportTeamMembersInExcel(string UserName, long? RoleId, string[] UserIds)
    {
        MemoryStream stream = new MemoryStream();
        FileContentResult robj;
        DataTable data = objuserservice.ExportTeamToExcel(UserName, RoleId, UserIds);
        using (XLWorkbook wb = new XLWorkbook())
        {
            wb.Worksheets.Add(data, "TeamMembers");
            using (stream)
            {
                wb.SaveAs(stream);
            }
        }
        robj = File(stream.ToArray(), System.Net.Mime.MediaTypeNames.Application.Octet, "TeamMembers.xlsx");
        return Json(robj, JsonRequestBehavior.AllowGet);
    }

无法打开文件,excel只是打开,然后不关闭自身,我什至在robj之前添加了stream.close(),但不起作用。
黎明代码

0

我听起来可能很幼稚,可能会引起很多批评,但是这就是我的做法,
它不涉及ajax出口,但也没有进行完整的回发

感谢这个职位和这个答案。
创建一个简单的控制器

public class HomeController : Controller
{               
   /* A demo action
    public ActionResult Index()
    {           
        return View(model);
    }
   */
    [HttpPost]
    public FileResult ExportData()
    {
        /* An example filter
        var filter = TempData["filterKeys"] as MyFilter;
        TempData.Keep();            */
        var someList = db.GetDataFromDb(/*filter*/) // filter as an example

    /*May be here's the trick, I'm setting my filter in TempData["filterKeys"] 
     in an action,(GetFilteredPartial() illustrated below) when 'searching' for the data,
     so do not really need ajax here..to pass my filters.. */

     //Some utility to convert list to Datatable
     var dt = Utility.ConvertToDataTable(someList); 

      //  I am using EPPlus nuget package 
      using (ExcelPackage pck = new ExcelPackage())
      {
          ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Sheet1");
          ws.Cells["A1"].LoadFromDataTable(dt, true);

            using (var memoryStream = new MemoryStream())
            {                   
              pck.SaveAs(memoryStream);
              return File(memoryStream.ToArray(),
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
              "ExportFileName.xlsx");                    
            }                
        }   
    }

    //This is just a supporting example to illustrate setting up filters ..        
   /* [HttpPost]
    public PartialViewResult GetFilteredPartial(MyFilter filter)
    {            
        TempData["filterKeys"] = filter;
        var filteredData = db.GetConcernedData(filter);
        var model = new MainViewModel();
        model.PartialViewModel = filteredData;

        return PartialView("_SomePartialView", model);
    } */     
} 

这是视图。

/*Commenting out the View code, in order to focus on the imp. code     
 @model Models.MainViewModel
 @{Layout...}     

      Some code for, say, a partial View  
      <div id="tblSampleBody">
        @Html.Partial("_SomePartialView", Model.PartialViewModel)
      </div>
  */                                                       
//The actual part.. Just **posting** this bit of data from the complete View...
//Here, you are not posting the full Form..or the complete View
   @using (Html.BeginForm("ExportData", "Home", FormMethod.Post))
    {
        <input type="submit" value="Export Data" />
    }
//...
//</div>

/*And you may require to pass search/filter values.. as said in the accepted answer..
That can be done while 'searching' the data.. and not while
 we need an export..for instance:-             

<script>             
  var filterData = {
      SkipCount: someValue,
      TakeCount: 20,
      UserName: $("#UserName").val(),
      DepartmentId: $("#DepartmentId").val(),     
   }

  function GetFilteredData() {
       $("#loader").show();
       filterData.SkipCount = 0;
       $.ajax({
          url: '@Url.Action("GetFilteredPartial","Home")',
          type: 'POST',
          dataType: "html",
          data: filterData,
          success: function (dataHTML) {
          if ((dataHTML === null) || (dataHTML == "")) {
              $("#tblSampleBody").html('<tr><td>No Data Returned</td></tr>');
                $("#loader").hide();
            } else {
                $("#tblSampleBody").html(dataHTML);                    
                $("#loader").hide();
            }
        }
     });
   }    
</script>*/

整个技巧似乎是,我们正在发布一个表单(Razor View 的一部分),在该表单上我们 调用 an Action method,该表单返回:a FileResult,并且此FileResult返回 the Excel File..
并发布过滤器值,如所述, ,如果您需要的话,我正在向其他动作提出要求,正如我们试图描述的那样。


-1

我正在使用Asp.Net WebForm,只是想从服务器端下载文件。有很多文章,但我找不到基本的答案。现在,我尝试了一种基本方法并获得了它。

那是我的问题。

我必须在运行时动态创建很多输入按钮。我想给每个按钮添加一个唯一的fileNumber来下载按钮。

我这样创建每个按钮:

fragment += "<div><input type=\"button\" value=\"Create Excel\" onclick=\"CreateExcelFile(" + fileNumber + ");\" /></div>";

每个按钮都调用此ajax方法。

$.ajax({
    type: 'POST',
    url: 'index.aspx/CreateExcelFile',
    data: jsonData,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (returnValue) {
      window.location = '/Reports/Downloads/' + returnValue.d;
    }
});

然后,我写了一个基本的简单方法。

[WebMethod]
public static string CreateExcelFile2(string fileNumber)
{
    string filePath = string.Format(@"Form_{0}.xlsx", fileNumber);
    return filePath;
}

我正在生成此Form_1,Form_2,Form_3...。并且我将使用另一个程序删除此旧文件。但是,如果有一种方法可以像使用Response那样仅发送字节数组来下载文件。我想使用它。

我希望这对任何人都有用。


-1

提交表单

public ActionResult ExportXls()
{   
 var filePath="";
  CommonHelper.WriteXls(filePath, "Text.xls");
}

 public static void WriteXls(string filePath, string targetFileName)
    {
        if (!String.IsNullOrEmpty(filePath))
        {
            HttpResponse response = HttpContext.Current.Response;
            response.Clear();
            response.Charset = "utf-8";
            response.ContentType = "text/xls";
            response.AddHeader("content-disposition", string.Format("attachment; filename={0}", targetFileName));
            response.BinaryWrite(File.ReadAllBytes(filePath));
            response.End();
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.