我的模型保存在客户端的JavaScript对象中,用户可以在其中通过UI控件编辑其属性。我想为用户提供一个选择,以下载代表他们编辑的模型的JSON文件。 是.NET
使用的
我
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>
6 Ajax Magic):
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
只能提出没有请求正文,用户的模型未传递给服务器,而下载的文件表示 somemodel
的默认实例。
问问
我知道我可以将模型发布到服务器,将其序列化给JSON并将JSON返回给客户端,我知道我可以让浏览器下载模型的JSON-Serialialized版本,但是我该怎么做在同一请求中都可以吗?
编辑:我已经接受的答案所做的是
xinran shen的答案,因为它起作用,但是因为我相信仅从堆栈溢出中复制代码而不了解它的作用或为什么不练习,所以我做了一些挖掘和我的版本 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();
}
希望有人能找到这个有用的
My model is held in a JavaScript object on the client side, where the user can edit its properties via the UI controls. I want to offer the user an option to download a JSON file representing the model they're editing. I'm using MVC core with .net 6.
What I've tried
Action method (using Newtonsoft.Json to serialize the model to 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");
}
Code in the view to call this method:
<button class="btn btn-primary" onclick="download()">Download</button>
And the event handler for this button (using jQuery's ajax magic):
function download() {
$.ajax({
url: 'https://hostname/ControllerName/Download',
method: 'POST',
data: { someModel: someModel },
success: function (data) {
console.log('downloading', data);
},
});
}
What happened
The browser console shows that my model has been posted to the server, serialized to JSON and the JSON has been returned to the browser. However no file is downloaded.
Something else I tried
I also tried a link like this to call the action method:
@Html.ActionLink("Download", "Download", "ControllerName")
What happened
This time a file was downloaded, however, because ActionLink
can only make GET requests, which have no request body, the user's model isn't passed to the server and instead the file which is downloaded represents a default instance of SomeModel
.
The ask
So I know I can post my model to the server, serialize it to JSON and return that JSON to the client, and I know I can get the browser to download a JSON-serialized version of a model, but how can I do both in the same request?
Edit: What I've done with the answer
I've accepted Xinran Shen's answer, because it works as-is, but because I believe that just copying code from Stack Overflow without understanding what it does or why isn't good practice, I did a bit of digging and my version of the saveData
function now looks like this:
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();
}
Hope someone finds this useful
发布评论
评论(2)
首先,您的代码是正确的,您可以尝试在没有AJAX的情况下访问此方法,您会发现它可以成功下载文件,但是您无法使用Ajax来实现此目的,因为JavaScript无法与磁盘进行交互,您需要使用Blob来保存文件。这样更改您的JavaScript:
First, Your code is right, You can try to access this method without ajax, You will find it can download file successfully,But You can't use ajax to achieve this, because JavaScript cannot interact with disk, you need to use Blob to save the file. change your javascript like this:
我认为您可能需要
fileStreamResult
,也需要将MIME类型设置为文本文件或JSON文件。参考:
I think you may need
FileStreamResult
, also you need to set the MIME type to text file or json file.Reference: https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/