typescript 如何从 ASP.NET Core 正确下载文件到 Angular?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48864518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to correctly download files to Angular from ASP.NET Core?
提问by Жуэль Итуа
I have a file on the server that I want to send to the client:
我在服务器上有一个文件要发送给客户端:
[HttpPost]
public IActionResult Test()
{
byte[] bytes = System.IO.File.ReadAllBytes(Path.Combine(FilesFolder, "test.docx"));
return File(bytes, _contentTypeWord);
}
I also tried with
我也试过
return PhysicalFile(pathUploadFile, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
At the client I accept using:
在客户端,我接受使用:
private _downloadFile(data: ArrayBuffer, fileName: string, contentType: string) {
var blob = new Blob([data], { type: contentType });
var url = window.URL.createObjectURL(blob);
var link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", fileName);
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
public test() {
this.http.post("Diplom/Test", { }, {
headers: this.headers(),
}).subscribe(
result => {
this._downloadFile(result.arrayBuffer(), "test.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
},
error => {
alert("Не удалось отредактировать файл");
console.error(JSON.stringify(error));
})
}
The file that the client receives is corrupt and does not open. The file that is on the server is fine and opens perfectly. The resulting file still does not open, and even weighs 2 times more (on the server 487 KB, and the client has 925 KB).
客户端收到的文件已损坏且无法打开。服务器上的文件很好,可以完美打开。结果文件还是打不开,甚至重了2倍(服务器上487 KB,客户端925 KB)。
回答by alsami
You can use a file result and just provide an api link that will return a FileContentResult.
您可以使用文件结果并只提供一个将返回FileContentResult的 api 链接。
public IActionResult Download(// some parameter)
{
// get the file and convert it into a bytearray
var locatedFile = ....
return new FileContentResult(locatedFile, new
MediaTypeHeaderValue("application/octet"))
{
FileDownloadName = "SomeFileDownloadName.someExtensions"
};
}
Now you only need to provide the link and browser will know how to handle it. No need to do it yourself then.
现在您只需要提供链接,浏览器就会知道如何处理它。那就不用自己动手了。
Edit:I just tested this approach with angular, you need to do the following to download the file when using angulars HttpClient.
编辑:我刚刚用 angular 测试了这种方法,在使用 angulars HttpClient时,您需要执行以下操作来下载文件。
First you need to install file-saver via npm.
首先,您需要通过 npm 安装文件保护程序。
npm i --save file-saver
Then in your module import and include HttpClientModule
然后在您的模块中导入并包含 HttpClientModule
import { HttpClientModule } from '@angular/common/http';
...
@NgModule({
imports: [
HttpClientModule
...
]
...
})
Now go ahead to your service and do the following
现在继续为您服务并执行以下操作
import { HttpClient } from '@angular/common/http';
import { saveAs } from 'file-saver';
@Injectable()
export class MyFileService {
public constructor(private http: HttpClient) {}
public downloadFile() {
this.http.get('my-api-url', { responseType: 'blob' }).subscribe(blob => {
saveAs(blob, 'SomeFileDownloadName.someExtensions', {
type: 'text/plain;charset=windows-1252' // --> or whatever you need here
});
});
}
Then blob is handled and a file-save dialog is created.
然后处理 blob 并创建文件保存对话框。
回答by Жуэль Итуа
I do not know why the option specified in the question does not work. But I found a solution, so to say "in another forest". I'm not very versed, so I'll just describe the process of solving the problem. For the beginning I will immediately say that the problem was on the client's side. The method on the server worked correctly from the start. I decided to use another method to download the files "fetch". And came across the next post in the forum. From there I took the following answer
我不知道为什么问题中指定的选项不起作用。但我找到了一个解决方案,可以说“在另一个森林中”。我不是很精通,所以我只描述解决问题的过程。首先,我会立即说问题出在客户端。服务器上的方法从一开始就正常工作。我决定使用另一种方法来下载文件“获取”。并在论坛中找到了下一个帖子。从那里我得到了以下答案
this.httpClient
.fetch(url, {method, body, headers})
.then(response => response.blob())
.then(blob => URL.createObjectURL(blob))
.then(url => {
window.open(url, '_blank');
URL.revokeObjectURL(url);
});
He did not work for me either. I changed it so
他也没有对我来说有效。我这样改了
fetch(url, {
method: 'POST',
headers: this.headers()
})
.then(response => response.blob())
.then(blob => URL.createObjectURL(blob))
.then(url => {
window.open(url, '_blank');
});
Because of this line nothing happened
因为这条线什么也没发生
URL.revokeObjectURL(url);
This option worked, but with screwed. He saved the file with a strange name and no extension. Then I changed it so.
此选项有效,但被搞砸了。他用一个奇怪的名字保存了这个文件,没有扩展名。然后我就这样改了。
fetch(url, {
method: 'POST',
headers: this.headers()
})
.then(response => response.blob())
.then(blob => URL.createObjectURL(blob))
.then(url => {
var link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "test.docx");
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
And it works! I apologize for the English. I'm using Google translator
它有效!我为英语道歉。我在用谷歌翻译
回答by Bharathkumar V
To download any file, first install the following,
要下载任何文件,请先安装以下内容,
npm install rxjs --save
npm install file-saver --save
Include these packages in your component(Angular 2+),
在你的组件中包含这些包(Angular 2+),
import { Observable } from 'rxjs';
import { saveAs } from 'file-saver';
import { map } from "rxjs/operators";
import { Subject } from 'rxjs';
import { HttpEventType, HttpClient } from '@angular/common/http';
Front-end code,
前端代码,
<input type="button" placeholder="Download" value="Download" (click)="download(file)" />
Angular Code,
角度代码,
download(file) {
let fileName = file;
let checkFileType = fileName.split('.').pop();
var fileType;
if (checkFileType == ".txt") {
fileType = "text/plain";
}
if (checkFileType == ".pdf") {
fileType = "application/pdf";
}
if (checkFileType == ".doc") {
fileType = "application/vnd.ms-word";
}
if (checkFileType == ".docx") {
fileType = "application/vnd.ms-word";
}
if (checkFileType == ".xls") {
fileType = "application/vnd.ms-excel";
}
if (checkFileType == ".png") {
fileType = "image/png";
}
if (checkFileType == ".jpg") {
fileType = "image/jpeg";
}
if (checkFileType == ".jpeg") {
fileType = "image/jpeg";
}
if (checkFileType == ".gif") {
fileType = "image/gif";
}
if (checkFileType == ".csv") {
fileType = "text/csv";
}
this.DownloadFile(fileName, fileType)
.subscribe(
success => {
saveAs(success, fileName);
},
err => {
alert("Server error while downloading file.");
}
);
}
DownloadFile(filePath: string, fileType: string): Observable<any> {
let fileExtension = fileType;
let input = filePath;
return this.http.get(this.yourApiUrl + "?fileName=" + input, {
responseType: 'blob',
observe: 'response'
})
.pipe(
map((res: any) => {
return new Blob([res.body], { type: fileExtension });
})
);
}
.NET Core API code,
.NET Core API 代码,
[HttpGet]
public async Task<FileStream> DownloadFile(string fileName)
{
return new FileStream(file, FileMode.Open, FileAccess.Read);
}