Javascript 如何下载Angular2或更高版本的文件
我有一个WebApi/MVC应用程序,我正在为它开发一个angular2客户端(以取代MVC)。我在理解Angular如何保存文件时遇到了一些问题 请求是可以的(MVC可以正常工作,我们可以记录收到的数据),但我不知道如何保存下载的数据(我主要遵循与中相同的逻辑)。我相信这是愚蠢的简单,但到目前为止,我只是没有掌握它 组件功能的代码如下所示。我尝试过不同的选择,blob方式应该是我所理解的方式,但是Javascript 如何下载Angular2或更高版本的文件,javascript,angular,typescript,download,fileapi,Javascript,Angular,Typescript,Download,Fileapi,我有一个WebApi/MVC应用程序,我正在为它开发一个angular2客户端(以取代MVC)。我在理解Angular如何保存文件时遇到了一些问题 请求是可以的(MVC可以正常工作,我们可以记录收到的数据),但我不知道如何保存下载的数据(我主要遵循与中相同的逻辑)。我相信这是愚蠢的简单,但到目前为止,我只是没有掌握它 组件功能的代码如下所示。我尝试过不同的选择,blob方式应该是我所理解的方式,但是URL中没有函数createObjectURL。我甚至在窗口中找不到URL的定义,但它显然存在。如
URL
中没有函数createObjectURL
。我甚至在窗口中找不到URL
的定义,但它显然存在。如果我使用了,我会得到同样的错误。所以我猜这是最近发生的变化,或者还没有实现。如何触发A2中的文件保存
下载文件(类型:字符串){
让文件={};
this.pservice.downloadfile(this.rundata.name,类型)
.subscribe(data=>thefile=newblob([data],{type:“application/octet stream”}),//console.log(data),
error=>console.log(“下载文件时出错”),
()=>console.log('已完成文件下载');
让url=window.url.createObjectURL(文件);
窗口打开(url);
}
为了完整性起见,获取数据的服务如下所示,但它所做的唯一事情是发出请求并在成功的情况下传递数据,而不进行映射:
下载文件(runname:string,type:string){
返回此.authHttp.get(this.files\u api+this.title+“/”+runname+“/?file=“+type)
.catch(this.logAndPassOn);
}
问题在于可观察对象在另一个上下文中运行,因此当您尝试创建URL变量时,您有一个空对象,而不是您想要的blob 解决这一问题的多种方法之一如下:
this.\u reportService.getReport().subscribe(数据=>this.downloadFile(数据)),//console.log(数据),
error=>console.log('下载文件时出错'),
()=>console.info('OK');
当请求准备就绪时,它将调用函数“downloadFile”,该函数定义如下:
下载文件(数据:响应){
const blob=new blob([data],{type:'text/csv'});
constURL=window.url.createObjectURL(blob);
窗口打开(url);
}
blob已经完全创建好了,因此URL变量,如果没有打开新窗口,请检查您是否已经导入了“rxjs/Rx”
导入'rxjs/Rx';
我希望这能对您有所帮助。正如上面提到的,这是一个简单的范围错误。subscribe
是异步运行的,必须将open
放在该上下文中,以便在触发下载时完成数据加载
也就是说,有两种方法。正如文档所建议的,该服务负责获取和映射数据:
//在服务上:
下载文件(runname:string,type:string){
var headers=新的headers();
append('responseType','arraybuffer');
返回此.authHttp.get(this.files\u api+this.title+“/”+runname+“/?file=“+type)
.map(res=>newblob([res],{type:'application/vnd.openxmlformats officedocument.spreadsheetml.sheet}))
.catch(this.logAndPassOn);
}
然后,在组件上,我们只需订阅并处理映射的数据。有两种可能性第一个,如原帖所示,但需要一点修正,如亚历杭德罗所述:
//在组件上
下载文件(类型:字符串){
this.pservice.downloadfile(this.rundata.name,类型)
.subscribe(数据=>window.open(window.URL.createObjectURL(数据)),
error=>console.log(“下载文件时出错”),
()=>console.log('已完成文件下载');
}
第二种方法是使用FileReader。逻辑是相同的,但我们可以显式地等待FileReader加载数据,避免嵌套,并解决异步问题
//在使用FileReader的组件上
下载文件(类型:字符串){
var reader=new FileReader();
this.pservice.downloadfile(this.rundata.name,类型)
.subscribe(res=>reader.readAsDataURL(res),
error=>console.log(“下载文件时出错”),
()=>console.log('已完成文件下载');
reader.onloadend=函数(e){
打开(reader.result'Excel','width=20,height=10,toolbar=0,menubar=0,scrollbars=no');
}
}
注意:我正在尝试下载Excel文件,即使已触发下载(因此这回答了问题),该文件也已损坏。用于避免损坏的文件。如果不需要在请求中添加标题,要下载Angular2格式的文件,可以执行简单的():
window.location.href=http://example.com/myuri/report?param=x';
在您的组件中。我分享了帮助我的解决方案(非常感谢任何改进) 在您的服务上“pservice”:
getMyFileFromBackend(typeName:string):可观察的通过ajax下载文件总是一个痛苦的过程,在我看来,最好让服务器和浏览器进行内容类型协商
我想最好是
去做吧。这甚至不需要打开任何新窗口之类的东西
示例中的MVC控制器可以如下所示:
[HttpGet(“[action]”)
公共异步任务下载文件()
{
// ...
返回文件(dataStream.ToArray(),“text/plain”,“myblob.txt”);
}
下载适用于angular 2.4.x的*.zip解决方案:您必须从“@angular/http”和chan导入ResponseContentType
npm install file-saver --save
npm install @types/file-saver --save
npm install file-saver --save
npm install @types/file-saver --save
import {saveAs} from 'file-saver/FileSaver';
this.http.get('endpoint/', {responseType: "blob", headers: {'Accept': 'application/pdf'}})
.subscribe(blob => {
saveAs(blob, 'download.pdf');
});
let headers = new Headers({
'Content-Type': 'application/json',
'MyApp-Application': 'AppName',
'Accept': 'application/vnd.ms-excel'
});
let options = new RequestOptions({
headers: headers,
responseType: ResponseContentType.Blob
});
this.http.post(this.urlName + '/services/exportNewUpc', localStorageValue, options)
.subscribe(data => {
if (navigator.appVersion.toString().indexOf('.NET') > 0)
window.navigator.msSaveBlob(data.blob(), "Export_NewUPC-Items_" + this.selectedcategory + "_" + this.retailname +"_Report_"+this.myDate+".xlsx");
else {
var a = document.createElement("a");
a.href = URL.createObjectURL(data.blob());
a.download = "Export_NewUPC-Items_" + this.selectedcategory + "_" + this.retailname +"_Report_"+this.myDate+ ".xlsx";
a.click();
}
this.ui_loader = false;
this.selectedexport = 0;
}, error => {
console.log(error.json());
this.ui_loader = false;
document.getElementById("exceptionerror").click();
});
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => сonsole.log(error),
() => console.log('Complete')
);
downloadFile(data: any, type: number, name: string) {
const blob = new Blob([data], {type: 'text/csv'});
const dataURL = window.URL.createObjectURL(blob);
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob);
return;
}
const link = document.createElement('a');
link.href = dataURL;
link.download = 'export file.csv';
link.click();
setTimeout(() => {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(dataURL);
}, 100);
}
}
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
// service method
downloadFiles(vendorName, fileName) {
return this.http.get(this.appconstants.filesDownloadUrl, { params: { vendorName: vendorName, fileName: fileName }, responseType: 'arraybuffer' }).map((res: ArrayBuffer) => { return res; })
.catch((error: any) => _throw('Server error: ' + error));
}
// a controller function which actually downloads the file
saveData(data, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
let blob = new Blob([data], { type: "octet/stream" }),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
// a controller function to be called on requesting a download
downloadFiles() {
this.service.downloadFiles(this.vendorName, this.fileName).subscribe(data => this.saveData(data, this.fileName), error => console.log("Error downloading the file."),
() => console.info("OK"));
}
<a href="my_url">Download File</a>
downloadfile(runname: string, type: string): string {
return window.location.href = `${this.files_api + this.title +"/"+ runname + "/?file="+ type}`;
}
<a download [attr.href]="yourDownloadLink"></a>
<div>
<a [href]="fileUrl" mat-raised-button (click)='getGenaratedLetterTemplate(element)'> GENARATE </a>
</div>
import { environment } from 'environments/environment';
import { DomSanitizer } from '@angular/platform-browser';
export class ViewHrApprovalComponent implements OnInit {
private apiUrl = environment.apiUrl;
fileUrl
constructor(
private sanitizer: DomSanitizer,
private letterService: LetterService) {}
getGenaratedLetterTemplate(letter) {
this.data.getGenaratedLetterTemplate(letter.letterId).subscribe(
// cannot download files directly with AJAX, primarily for security reasons);
console.log(this.apiUrl + 'getGeneratedLetter/' + letter.letterId);
this.fileUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.apiUrl + 'getGeneratedLetter/' + letter.letterId);
}
this.httpclient.get(
`${myBackend}`,
{
observe: 'response',
responseType: 'blob'
}
).pipe(first())
.subscribe(response => SaveFileResponse(response, 'Custom File Name.extension'));
export const SaveFileResponse =
(response: HttpResponse<Blob>,
filename: string = null) =>
{
//null-checks, just because :P
if (response == null || response.body == null)
return;
let serverProvidesName: boolean = true;
if (filename != null)
serverProvidesName = false;
//assuming the header is something like
//content-disposition: attachment; filename=TestDownload.xlsx; filename*=UTF-8''TestDownload.xlsx
if (serverProvidesName)
try {
let f: string = response.headers.get('content-disposition').split(';')[1];
if (f.includes('filename='))
filename = f.substring(10);
}
catch { }
SaveFile(response.body, filename);
}
//Create an anchor element, attach file to it, and
//programmatically click it.
export const SaveFile = (blobfile: Blob, filename: string = null) => {
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blobfile);
a.download = filename;
a.click();
}
downloadFile(x: any) {
var newBlob = new Blob([x], { type: "application/octet-stream" });
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
// For other browsers:
// Create a link pointing to the ObjectURL containing the blob.
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
link.href = data;
link.download = "mapped.xlsx";
// this is necessary as link.click() does not work on the latest firefox
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
setTimeout(function () {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(data);
link.remove();
}, 100); }
let link = document.createElement('a');
link.href = data.fileurl; //data is object received as response
link.download = data.fileurl.substr(data.fileurl.lastIndexOf('/') + 1);
link.click();
public exportAsExcelFile(dataId: InputData) {
return this.http.get(this.apiUrl + `event/export/${event.id}`, {
responseType: "blob",
observe: "response"
}).pipe(
tap(response => {
this.downloadFile(response.body, this.parseFilename(response.headers.get('Content-Disposition')));
})
);
}
private downloadFile(data: Blob, filename: string) {
const blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;'});
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
if (link.download !== undefined) {
// Browsers that support HTML5 download attribute
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
private parseFilename(contentDisposition): string {
if (!contentDisposition) return null;
let matches = /filename="(.*?)"/g.exec(contentDisposition);
return matches && matches.length > 1 ? matches[1] : null;
}
private object ConvertFileResponse(ExcelOutputDto excelOutput)
{
if (excelOutput != null)
{
ContentDisposition contentDisposition = new ContentDisposition
{
FileName = excelOutput.FileName.Contains(_excelExportService.XlsxExtension) ? excelOutput.FileName : "TeamsiteExport.xlsx",
Inline = false
};
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
Response.Headers.Add("Content-Disposition", contentDisposition.ToString());
return File(excelOutput.ExcelSheet, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
else
{
throw new UserFriendlyException("The excel output was empty due to no events.");
}
}