英文:
Problem Returning file from ASP.NET Core MVC Controller- File is not downloaded
问题
我正在尝试创建一个在浏览器中启动文件下载的“下载”按钮。
以下是我的Controller代码:
[HttpGet("AdminTools/{batchId}/DownloadAnswers")]
public async Task<FileResult> DownloadAnswers(int batchId)
{
string fileName = "test.txt";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, MimeHelper.GetMimeMapping(fileName), fileName);
}
这段代码应该从数据库中获取数据,并创建一个CSV文件以供下载,但我已经简化了代码。
在视图中,我有一个按钮,使用Knockout进行数据绑定:
<button class="btn btn-light" data-bind="click: () => $parent.downloadAnswers(line.BatchId)">
<i class="fad fa-file-download fa-fw"></i> Download
</button>
以及我的viewModel中的代码:
downloadAnswers(batchId: number) {
Q($.ajax({
url: `/Attestering/AdminTools/${batchId}/DownloadAnswers/`,
type: 'GET'
}));
}
当我点击按钮时,我得到以下响应:
请求头:
GET /Attestering/AdminTools/91/DownloadAnswers/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: da-DK,da;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Cookie: .AspNetCore.Antiforgery.QdXrCqqGsrk=CfDJ8KXm89uE_DNAripaOM8IAxzND7VK_PQPxpfmXtgTsKY1uN3acIgiucBdlkKaXs_eJvQu2Te066RjYnOlazo2P1oKclowja9hkxKhzrwIzq8GHhmsAhA_ZLQbMoFg59FeSEfExF04U6KJYk0W-Whhb1A
Host: localhost:7777
Pragma: no-cache
Referer: https://localhost:7777/attestering/admintools
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
响应头:
HTTP/1.1 200 OK
Content-Length: 12
Content-Type: text/plain
Date: Tue, 07 Mar 2023 13:34:44 GMT
Server: Kestrel
Content-Disposition: attachment; filename=test.txt; filename*=UTF-8''test.txt
响应体:
Hello World!
但我没有收到文件下载。我已经尝试了许多不同的方法,主要在控制器部分。有没有提示?
英文:
I'm trying to build a "download" button that starts a file download in the browser.
Here is my Controller:
[HttpGet("AdminTools/{batchId}/DownloadAnswers")]
public async Task<FileResult> DownloadAnswers(int batchId)
{
string fileName = "test.txt";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, MimeHelper.GetMimeMapping(fileName), fileName);
}
It is supposed to grab data from a database, and create a CSV file for delivery, but i've slimmed down the code.
In the view i have this button using knockout to data-bind click
<button class="btn btn-light" data-bind="click: () => $parent.downloadAnswers(line.BatchId)"><i class="fad fa-file-download fa-fw"></i> Download </button>
and the code in my viewModel
downloadAnswers(batchId: number) {
Q($.ajax({
url: `/Attestering/AdminTools/${batchId}/DownloadAnswers/`,
type: 'GET'
}));
}
When I click the button I get this response:
Request headers:
GET /Attestering/AdminTools/91/DownloadAnswers/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: da-DK,da;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Cookie: .AspNetCore.Antiforgery.QdXrCqqGsrk=CfDJ8KXm89uE_DNAripaOM8IAxzND7VK_PQPxpfmXtgTsKY1uN3acIgiucBdlkKaXs_eJvQu2Te066RjYnOlazo2P1oKclowja9hkxKhzrwIzq8GHhmsAhA_ZLQbMoFg59FeSEfExF04U6KJYk0W-Whhb1A
Host: localhost:7777
Pragma: no-cache
Referer: https://localhost:7777/attestering/admintools
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
And this Reponse header:
HTTP/1.1 200 OK
Content-Length: 12
Content-Type: text/plain
Date: Tue, 07 Mar 2023 13:34:44 GMT
Server: Kestrel
Content-Disposition: attachment; filename=test.txt; filename*=UTF-8''test.txt
And this Reponse
Hello World!
But I don't get the file download.
I've been searching and trying many different things. Mostly on the controller side.
Any hints ?
答案1
得分: 0
你的控制器部分是正常的,如果你可以通过MimeHelper.GetMimeMapping(fileName)
获取正确的内容类型,但由于你尝试使用ajax调用,所以失败了,你会在ajax调用的响应中获取文件内容(例如作为字符串),而不是文件。
我尝试了两种解决方案,希望能帮助你:
<input type="button" onclick="downloadtxt()" value="DownloadTxt"/>
<input type="button" onclick="downloadcsv()" value="DownloadCSV"/>
<script>
function downloadtxt(){
window.open("/Home/DownloadTxt")
}
function downloadcsv(){
var eleForm = $("<form method='get'></form>");
eleForm.attr("action","/Home/DownloadCsv");
$(document.body).append(eleForm);
eleForm.submit();
}
</script>
控制器部分:
[HttpGet]
public async Task<FileResult> DownloadTxT( )
{
string fileName = "test.txt";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, "text/plain", fileName);
}
[HttpGet]
public async Task<FileResult> DownloadCSV()
{
string fileName = "test.csv";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, "text/csv", fileName);
}
结果:
英文:
Your controller side is OK,if you could get the correct content-type with MimeHelper.GetMimeMapping(fileName)
, you failed just because you tried with an ajax call,you would get the content of the file (for example as string) in resopnse of ajax call instead of the file
I tried with the two solutions,hopes could help:
<input type="button" onclick="downloadtxt()" value="DownloadTxt"/>
<input type="button" onclick="downloadcsv()" value="DownloadCSV"/>
<script>
function downloadtxt(){
window.open("/Home/DownloadTxt")
}
function downloadcsv(){
var eleForm = $("<form method='get'></form>");
eleForm.attr("action","/Home/DownloadCsv");
$(document.body).append(eleForm);
eleForm.submit();
}
</script>
Controller:
[HttpGet]
public async Task<FileResult> DownloadTxT( )
{
string fileName = "test.txt";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, "text/plain", fileName);
}
[HttpGet]
public async Task<FileResult> DownloadCSV()
{
string fileName = "test.csv";
byte[] filebytes = Encoding.UTF8.GetBytes("Hello World!");
return File(filebytes, "text/csv", fileName);
}
Result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论