我的模型保存在客户端的JavaScript对象中,用户可以通过UI控件编辑其属性。我想为用户提供一个下载JSON文件的选项,该文件表示他们正在编辑的模型。我正在使用MVC核心与。net 6。
我已经试过了
动作方法(使用Newtonsoft。(将模型序列化为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");
}
视图中调用此方法的代码:
<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已经返回到浏览器。但是没有文件下载。
我还试过别的东西
我还尝试了一个这样的链接来调用action方法:
@Html.ActionLink("Download", "Download", "ControllerName")
发生了什么这次下载了一个文件,但是,因为ActionLink
只能发出没有请求体的GET请求,所以没有将用户的模型传递给服务器,而是下载的文件代表SomeModel
的默认实例。
问所以我知道我可以将我的模型发布到服务器,将其序列化为JSON并将该JSON返回给客户端,我知道我可以让浏览器下载JSON序列化版本的模型,但我如何在同一个请求中做到这两点?
编辑:我对答案做了什么
我已经接受了欣然沈的回答,因为它按原样工作,但因为我相信只是从堆栈溢出复制代码而不了解它的作用或为什么不是好的做法,我做了一些挖掘,我的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);
};
}());
我认为您可能需要FileStreamResult
,还需要将MIME类型设置为文本文件或json文件。
// instead of this
return this.File(stream, "APPLICATION/octet-stream", "someFile.json");
// try this
return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
{
FileDownloadName = "someFile.txt"
};
// or
return new FileStreamResult(stream, new MediaTypeHeaderValue("application/json"))
{
FileDownloadName = "someFile.json"
};
参考:https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/