0

我的 MVC 应用程序中有一个 C# 函数,它返回 csv 文件的 JSON 表示。我试图在 javascript 中捕获它并打开文件。基本上我希望浏览器做它的事情,让用户决定他是要打开它,保存它还是取消它。我无法让该弹出窗口要求我打开文件。下面是函数

C# 函数

[HttpPost]
public ActionResult ExportToCsv(string fileContents, string fileName)
{
    fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
    return Json(new { url = File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName) }); ;
}

这是我对函数进行 ajax 调用的 javascript

$("#btnExport").click(function (event) {
    event.preventDefault();
    var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
    $.ajax({
        url: "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv",
        type: 'Post',
        success: function (result) {
            window.open(result.url);
        }
    });
});

我知道我错过了一些东西。有人可以帮忙吗。

编辑

在阅读了所有可能的答案和评论后,这就是我想要实现的目标。因此,如果我的代码完全错误,请告诉我。

我有一个网格,我有一个导出到 excel 按钮。我有一种方法可以将我想要的数据转换为 javascript 本身中的逗号分隔文本。我需要将此作为可下载的 csv 文件呈现给用户。为此,我使用控制器方法创建了 File 对象。以前的化身是一个 Get 方法,由于查询字符串的长度限制,我遇到了限制。所以我尝试将其转换为 POST 方法,但它不起作用。

这是适用于少量数据的代码的早期版本

Javascript

   $("#btnExport").click(function (event) {
            event.preventDefault();
            var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
            window.location.href = "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv";
        });

C# 函数

    [HttpGet]
    public ActionResult ExportToCsv(string fileContents, string fileName)
    {
        fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
        return File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName);
    }

希望这现在可以为您提供更多背景信息。基本上我需要将我的 GET 方法转换为 POST 方法并从 Javascript 中使用它。

4

3 回答 3

0

您不能使用 ajax 保存二进制文件 - 由于安全原因,它受到限制。如果您希望用户保存文件 - 当您以 JSON 格式发回数据时,从控制器返回二进制流(即,如果用户想要保存它)。

我在这里做了类似的事情:如何在 .net MVC4 上正确创建和下载动态生成的二进制 *.xlsx 文件?

于 2013-11-14T23:14:57.393 回答
0

也许将其保存为 json 文件并加载到当前页面的 DOM 中。尽管我很困惑,但您是否只有一个包含指向您的 CSV 文件的 URL 的 JSON 响应,这只是一个 CSV 文件,而不是 CSV 的 JSON 表示?

$("#btnExport").click(function (event) {
        event.preventDefault();
        var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
        $.ajax({
            url: "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.json",
            type: 'Post',
            success: function (result) {
                var myDummyElement = $('<div>'); //dummy div so you can call load
                myDummyElement .load('result.url #myJson');
            }
        });
    });

<div id="myJson"></div>

[HttpPost]
    public ActionResult ExportToCsv(string fileContents, string fileName)
    {
        //change fileName to be a .json extension
        fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
        return Json(new { url = File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName) }); ;
    }
于 2013-11-14T23:16:57.350 回答
0

如果您使用ajax,您需要在代码中处理结果。但是您不能以这种方式(直接)触发文件下载。

相反,创建一个 (hidden)form并将其发布到 (hidden) iframe(通过给出iframeaname并将其指定为targetthe form),确保响应指定 header Content-Disposition: attachment。这将触发浏览器提供保存文件。(可选)在标题中,您可以通过添加; filename="fname.ext"到标题值来建议文件的文件名。例如Content-Disposition: attachment; filename="fname.ext"

客户端看起来像这样:

$("#btnExport").click(function (event) {
    event.preventDefault();
    var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
    var frame = $('iframe[name="formreceiver"]');
    if (!frame.length) {
        frame = $('<iframe name="formreceiver"></iframe>').appendTo(document.body).css("display", "none");
    }
    var form = $("#senderform");
    if (!form.length) {
        form = $('<form id="senderform"></form>').appendTo(document.body);
    }
    form = form[0]; // Raw DOM element rather than jQuery wrapper
    form.target = "formreceiver";
    form.action = "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv";
    form.method = "POST";
    form.submit();
});

服务器端只是带有Content-Disposition标头的标准表单响应。

我多年来一直使用这种技术,从 IE6 开始的浏览器。我通常的设置已经包含iframe在标记中(而不是像上面那样创建它),但除此之外,这基本上就是我所做的。

请注意,您这样做是为了响应用户的按钮单击,这一点很重要。如果不是这样,就会出现弹出窗口阻止程序问题。

于 2013-11-14T23:21:15.880 回答