download - 如何将模型下载为 JSON 文件?

标签 download asp.net-core-mvc javascript-objects

我的模型保存在客户端的 JavaScript 对象中,用户可以在其中通过 UI 控件编辑其属性。我想为用户提供一个选项来下载代表他们正在编辑的模型的 JSON 文件。我在 .net 6 中使用 MVC 核心。

我尝试过的

Action方法(使用Newtonsoft.Json将模型序列化为JSON):

public IActionResult Download([FromForm]SomeModel someModel)
{
    var json = JsonConvert.SerializeObject(someModel);
    var characters = json.ToCharArray();
    var bytes = new byte[characters.Length];
    for (var i = 0; i < characters.Length; i++)
    {
        bytes[i] = (byte)characters[i];
    }

    var stream = new MemoryStream();
    stream.Write(bytes);
    stream.Position = 0;
    return this.File(stream, "APPLICATION/octet-stream", "someFile.json");
}

View 中调用此方法的代码:

<button class="btn btn-primary" onclick="download()">Download</button>

以及此按钮的事件处理程序(使用 jQuery 的 ajax 魔法):

function download() {
    $.ajax({
        url: 'https://hostname/ControllerName/Download',
        method: 'POST',
        data: { someModel: someModel },
        success: function (data) {
            console.log('downloading', data);
        },
    });
}

发生了什么

浏览器控制台显示我的模型已经发布到服务器,序列化为 JSON 并且 JSON 已经返回给浏览器。但是没有文件被下载。

我尝试过的其他东西

我也尝试过这样的链接来调用操作方法:

@Html.ActionLink("Download", "Download", "ControllerName")

发生了什么

但是这次下载了一个文件,因为 ActionLink 只能发出没有请求主体的 GET 请求,所以用户的模型不会传递给服务器,而是下载的文件表示 SomeModel 的默认实例。

提问

所以我知道我可以将我的模型发布到服务器,将其序列化为 JSON 并将该 JSON 返回给客户端,并且我知道我可以让浏览器下载模型的 JSON 序列化版本,但我如何才能在同一个请求中执行这两个操作?

编辑:我对答案做了什么

我已经接受了 Xinran Shen's answer ,因为它按原样工作,但因为我相信只是从 Stack Overflow 复制代码而不理解它的作用或为什么不是好的做法,我做了一些挖掘和我的 saveData 函数现在看起来像这样:

function saveData(data, fileName) {
    // Convert the data to a JSON string and store it in a blob, a file-like
    // object which can be downloaded without it existing on the server.
    // See https://developer.mozilla.org/en-US/docs/Web/API/Blob
    var json = JSON.stringify(data);
    var blob = new Blob([json], { type: "octet/stream" });

    // Create a URL from which the blob can be downloaded - see
    // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
    var url = window.URL.createObjectURL(blob);

    // Add a hidden hyperlink to the page, which will download the file when clicked
    var a = document.createElement("a");
    a.style = "display: none";
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);

    // Trigger the click event on the hyperlink to download the file
    a.click();

    // Release the blob's URL.
    // Browsers do this when the page is unloaded, but it's good practice to
    // do so as soon as it's no longer needed.
    window.URL.revokeObjectURL(url);

    // Remove the hidden hyperlink from the page
    a.remove();
}

希望有人觉得这有用

最佳答案

首先,你的代码是对的,你可以尝试不使用ajax访问这个方法,你会发现它可以成功下载文件,但是你不能使用ajax来实现这个,因为JavaScript不能与磁盘交互,你需要使用 Blob 保存文件。像这样更改您的 javascript:

function download() {
            
            $.ajax({
                url: 'https://hostname/ControllerName/Download',
                method: 'Post',
                data: { someModel: someModel },,
                
                success: function (data) {
                            fileName = "my-download.json";
                            saveData(data,fileName)
                        },
                        
            });
        }
        
        var saveData = (function () {
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            return function (data, fileName) {
                var json = JSON.stringify(data),
                    blob = new Blob([json], {type: "octet/stream"}),
                    url = window.URL.createObjectURL(blob);
                a.href = url;
                a.download = fileName;
                a.click();
                window.URL.revokeObjectURL(url);
            };
        }());

关于download - 如何将模型下载为 JSON 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72848245/

相关文章:

jakarta-ee - Tomcat 是否有等同于 GlassFish "Alternate Document Roots"的东西?

image - golang api 图像下载中的图像文件损坏

delphi - UrlDownloadToFile 在 Delphi XE2 中不起作用?

asp.net-core-mvc - 使用 ASP.NET Core MVC 6 将编辑器模板放在 View 的文件夹中

javascript - 返回值并提供对内部定义方法的访问的函数

javascript - 在 ReactJS 中处理未定义值的最佳方式?

ios - 如何在 iOS 应用程序中防止来电干扰

visual-studio-2015 - Visual Studio 2015 不考虑 ASP.NET Core 项目的 nuget 存储库路径

asp.net-core-mvc - 如何使用 Swashbuckle 的 SwaggerUI 来显示静态 swagger.json 文件而不是 SwaggerGen 的动态创建的定义?

javascript - 通过 "path"数组删除嵌套对象属性