Ajax 如何在.net MVC4上正确创建和下载动态生成的二进制*.xlsx文件?

Ajax 如何在.net MVC4上正确创建和下载动态生成的二进制*.xlsx文件?,ajax,asp.net-mvc-4,export-to-excel,xlsx,Ajax,Asp.net Mvc 4,Export To Excel,Xlsx,我需要制作一个“导出到excel”功能 Excel是一个二进制文件,如果您使用其XML格式,它会在msExcel上发送警告 我目前正在做的是用我的所有数据保留一个状态对象(因为我需要知道用户正在做的各种更改),并使用ajax将其传递给一个.net MVC控制器,该控制器使用一个库来创建*.xlsx文件 客户端: $.ajax({ type: "POST", url: "/path/to/exportController", data: exporter.getData(

我需要制作一个“导出到excel”功能

Excel是一个二进制文件,如果您使用其XML格式,它会在msExcel上发送警告

我目前正在做的是用我的所有数据保留一个状态对象(因为我需要知道用户正在做的各种更改),并使用ajax将其传递给一个.net MVC控制器,该控制器使用一个库来创建*.xlsx文件

客户端:

 $.ajax({
    type: "POST",
    url: "/path/to/exportController",
    data: exporter.getData(),
    success: success,
    error: error,
    dataType: 'json'
 });
服务器端:

 public ActionResult Excel(mySpecialandIrrelevantDescriptiveClass jsonData)
    {
      //excel generation logic
      .....
    }
现在从我的角度来看,我有3个选择:

  • 创建一个流并将其推送回ajax请求——但从我收集的信息来看,ajax不能真正用生成的二进制流推送下载请求

  • 将文件保存在服务器硬盘上,返回一个公共url,并用新url打开一个新的弹出窗口,获得下载提示,然后以某种方式关闭窗口,使其看起来不那么难看

  • 忘记ajax吧,将所有内容放入一些隐藏的表单字段并将其发布到服务器,再次打开一个新窗口并等待响应,然后关闭它

  • 选项#2要求我创建一个任务,该任务将不断清除生成的文件和URL,这是一个巨大的麻烦,因为该平台仅此功能就可以获得约10-20k的点击率


    实现我所需要的最好方法是什么?

    有很多这样的问题:

    我可以继续说:)

    总之,他们都建议通过
    窗口使用某种重定向


    这可能是一种方法,但是如果你觉得足够冒险,我也会尝试HTML5 Blob API、文件系统和/或类型化数组的组合。

    因此我最终得到了它:

    您不能使用ajax返回二进制文件—您将收到其数据—但无法显示二进制文件

    我将其用作excel库,并通过通用HTML表单隐藏字段中的post方法传递数据。 输出是使用流作为返回值生成的,因此用户可以在页面上保持不刷新/重定向

    服务器:

    //the expected data description - automatic tool @ http://json2csharp.com/
    public class ExpectedJSON
    {
        public class SomeDataSet
        {
            public string dude{ get; set; }
            public string what { get; set; }
            public string foo { get; set; }
            public string bar { get; set; }
            public string baz { get; set; }
            public int asd { get; set; }
            public string someDate { get; set; }
            public string wat { get; set; }
            public string grrr { get; set; }
        }
    
        public class AnotherDataSet
        {
            public int type { get; set; }
            public string date { get; set; }
            public string dancing { get; set; }
            public double camels { get; set; }
            public int are { get; set; }
            public int crying { get; set; }
            public double _for { get; set; }
            public double some { get; set; }
            public double beer { get; set; }
        }
    
        public class MoreData
        {
            public int dark { get; set; }
            public double side { get; set; }
            public int of { get; set; }
            public int the { get; set; }
            public double moon { get; set; }
            public double iz { get; set; }
            public double da { get; set; }
            public string bomb { get; set; }
        }
    }
    
    public class ExportToController : Controller
    {
        public ActionResult Excel([FromUri(Name= "someData")] string someDataSet,
                                  [FromUri(Name = "anotherData")] string anotherDataSet,
                                  [FromUri(Name = "moreData")] string moreData)
        {
            ExpectedJSON.SomeDataSet someDataSetJson = JsonConvert.DeserializeObject<ExpectedJSON.SomeDataSet>(someData);
            ExpectedJSON.AnotherDataSet[] anotherDataSetJson = JsonConvert.DeserializeObject<Campaign.OnlineComulativeDailyBuildChart[]>(anotherData);
            ExpectedJSON.MoreData[] moreDataJson = JsonConvert.DeserializeObject<Campaign.OnlineSitesGrid[]>(moreData);
            string fileName = "file.xlsx";
    
            ExcelPackage p = new ExcelPackage();
            p.Workbook.Worksheets.Add("Some Sheet");
            ExcelWorksheet ws = p.Workbook.Worksheets[1];
    
            //excel library logic follows...
    
            //...
            //..
    
    
           //stream logic
    
            MemoryStream stream = new MemoryStream(p.GetAsByteArray());
    
    
            FileStreamResult result = new FileStreamResult(stream, "application/vnd.ms-excel")
            {
                FileDownloadName = fileName
            };
    
            return result;
        }
    }
    

    使用rails/sinatra/nodeJS只需几分钟,使用.net只需几天/几周,但你就可以做到了。

    如果你注意到这一点,你会发现使用ajax下载文件是不可能的:你可以接收二进制文件的数据,但你没有任何方法将其显化。为了实现这一点,你可以使用flash,类似于Downloadify,不过你知道,flash:)谢谢你的提示,会让每个人都发帖的。是的,我知道了,大多数解决方案都是将这些数据重定向到某种mime类型的url。我相信它也可以通过HTML5 blob api实现。
    <form id="exportToExcel" action="../ExportTo/Excel/" target="_blank" method="post">
      <input type="hidden" id="someData" name="someData" />
      <input type="hidden" id="anotherData" name="anotherData" />
      <input type="hidden" id="moreData" name="moreData" />
      <button type="submit">export</button>
    </form>
    
    function bindEvents() {
        var exportForm = $("#exportToExcel");
        var someData= exportForm.find("#someData");
        var anotherData= exportForm.find("#anotherData");
        var moreData = exportForm.find("#moreData");
        exportForm.on('submit', function (e) {
            someData.attr("value", JSON.stringify(exporter.getData().someData));
            anotherData.attr("value", JSON.stringify(exporter.getData().anotherData));
            moreData .attr("value", JSON.stringify(exporter.getData().moreData));
        });
    }