我的模型保存在客户端的 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/