如何使用Angular2下载文件

我有一个WebApi / MVC应用程序,我正在开发一个angular2客户端(以取代MVC)。 我有一些麻烦了解Angular如何保存文件。

请求是好的(与MVC工作正常,我们可以logging收到的数据),但我不知道如何保存下载的数据(我大多遵循在这篇文章中相同的逻辑)。 我相信这简直是愚蠢的,但到目前为止,我根本就没有把握。

组件函数的代码如下所示。 我已经尝试了不同的select,blob方式应该是我所了解的方式,但URL没有函数createObjectURL 。 我甚至无法在窗口中findURL的定义,但显然它存在。 如果我使用FileSaver.js模块 , FileSaver.js得到相同的错误。 所以我想这是最近改变的或者还没有实施的东西。 如何触发保存在A2中的文件?

 downloadfile(type: string){ let thefile = {}; this.pservice.downloadfile(this.rundata.name, type) .subscribe(data => thefile = new Blob([data], { type: "application/octet-stream" }), //console.log(data), error => console.log("Error downloading the file."), () => console.log('Completed file download.')); let url = window.URL.createObjectURL(thefile); window.open(url); } 

为了完整起见,获取数据的服务如下,但它唯一做的是发出请求并传递数据,如果成功则不映射:

 downloadfile(runname: string, type: string){ return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type) .catch(this.logAndPassOn); } 

注:我知道这不是一个最小的工作示例,但我已经花费了很多精力来解决问题。 如果你要downvote请留下评论。

问题是observable在另一个上下文中运行,所以当你尝试创buildURL var时,你有一个空的对象而不是你想要的blob。

解决这个问题的方法之一就是:

 this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data), error => console.log("Error downloading the file."), () => console.info("OK"); 

当请求准备就绪时,它将调用函数“downloadFile”,定义如下:

 downloadFile(data: Response){ var blob = new Blob([data], { type: 'text/csv' }); var url= window.URL.createObjectURL(blob); window.open(url); } 

blob已经完美创build,所以URL var,如果不打开新窗口,请检查您是否已经导入了'rxjs / Rx';

  import 'rxjs/Rx' ; 

希望这可以帮助你。

尝试这个!

1 – 安装显示保存/打开文件popup窗口的依赖关系

 npm install file-saver --save npm install @types/file-saver --save 

2-使用此function创build服务以重新获取数据

 downloadFile(id): Observable<Blob> { let options = new RequestOptions({responseType: ResponseContentType.Blob }); return this.http.get(this._baseUrl + '/' + id, options) .map(res => res.blob()) .catch(this.handleError) } 

3-在组件parsingblob与'文件保护程序'

 import {saveAs as importedSaveAs} from "file-saver"; this.myService.downloadFile(this.id).subscribe(blob => { importedSaveAs(blob, this.fileName); } ) 

这对我有用!

正如Alejandro Corredor所提到的,这是一个简单的范围错误。 该subscribe是asynchronous运行的,并且必须将open放置在该上下文中,以便在触发下载时完成数据加载。

也就是说,有两种方法可以做到这一点。 由于文档build议服务负责获取和映射数据:

 //On the service: downloadfile(runname: string, type: string){ var headers = new Headers(); headers.append('responseType', 'arraybuffer'); return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type) .map(res => new Blob([res],{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })) .catch(this.logAndPassOn); } 

然后,在组件上,我们只需订阅并处理映射的数据。 有两种可能性。 第一个 ,正如原来的post所build议的那样,但是需要像Alejandro指出的那样进行一些小的修正:

 //On the component downloadfile(type: string){ this.pservice.downloadfile(this.rundata.name, type) .subscribe(data => window.open(window.URL.createObjectURL(data)), error => console.log("Error downloading the file."), () => console.log('Completed file download.')); } 

第二种方法是使用FileReader。 逻辑是相同的,但我们可以明确地等待FileReader加载数据,避免嵌套,并解决asynchronous问题。

 //On the component using FileReader downloadfile(type: string){ var reader = new FileReader(); this.pservice.downloadfile(this.rundata.name, type) .subscribe(res => reader.readAsDataURL(res), error => console.log("Error downloading the file."), () => console.log('Completed file download.')); reader.onloadend = function (e) { window.open(reader.result, 'Excel', 'width=20,height=10,toolbar=0,menubar=0,scrollbars=no'); } } 

注:我试图下载一个Excel文件,即使下载被触发(所以这回答了这个问题),该文件已损坏。 请参阅这篇文章的回答,以避免损坏的文件。

下载2.4.x的* .zip解决scheme:您必须从'@ angular / http'导入ResponseContentType并将ResponseType更改为ResponseContentType.ArrayBuffer(默认情况下为ResponseContentType.Json)

 getZip(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> { let headers = this.setHeaders({ 'Content-Type': 'application/zip', 'Accept': 'application/zip' }); return this.http.get(`${environment.apiUrl}${path}`, { headers: headers, search: params, responseType: ResponseContentType.ArrayBuffer //magic }) .catch(this.formatErrors) .map((res:Response) => res['_body']); } 

通过ajax下载文件总是一个痛苦的过程,我认为最好让服务器和浏览器做这个内容types协商的工作。

我认为最好有

 <a href="api/sample/download"></a> 

去做吧。 这甚至不需要任何新的窗口打开和这样的东西。

您的示例中的MVC控制器可能如下所示:

 [HttpGet("[action]")] public async Task<FileContentResult> DownloadFile() { ... return File(dataStream.ToArray(), "text/plain", "myblob.txt"); } 

如果您不需要在请求中添加标题,那么要在Angular2中下载文件,您可以做一个简单的操作:

 window.location.href='http://example.com/myuri/report?param=x'; 

在你的组件。

我分享帮助我的解决scheme(非常感谢任何改进)

在你的服务 'pservice'上:

 getMyFileFromBackend(typeName: string): Observable<any>{ let param = new URLSearchParams(); param.set('type', typeName); // setting 'responseType: 2' tells angular that you are loading an arraybuffer return this.http.get(http://MYSITE/API/FILEIMPORT, {search: params, responseType: 2}) .map(res => res.text()) .catch((error:any) => Observable.throw(error || 'Server error')); } 

组件部分:

 downloadfile(type: string){ this.pservice.getMyFileFromBackend(typename).subscribe( res => this.extractData(res), (error:any) => Observable.throw(error || 'Server error') ); } extractData(res: string){ // transforme response to blob let myBlob: Blob = new Blob([res], {type: 'application/vnd.oasis.opendocument.spreadsheet'}); // replace the type by whatever type is your response var fileURL = URL.createObjectURL(myBlob); // Cross your fingers at this point and pray whatever you're used to pray window.open(fileURL); } 

在组件部分,您调用服务而不订阅响应。 订阅openOffice MIMEtypes的完整列表,请参阅: http : //www.openoffice.org/framework/documentation/mimetypes/mimetypes.html

这个怎么样?

 this.http.get(targetUrl,{responseType:ResponseContentType.Blob}) .catch((err)=>{return [do yourself]}) .subscribe((res:Response)=>{ var a = document.createElement("a"); a.href = URL.createObjectURL(res.blob()); a.download = fileName; // start download a.click(); }) 

我可以用它做。
不需要额外的包装。

您好我得到解决scheme从angular2下载没有得到腐败….使用弹簧mvc和angular2

第一 – 我的返回types是: – 从Java结束ResponseEntity ….在这里,我发送byte []数组从控制器返回types。

第二步 – 在工作区中包含文件保存器 – 在索引页中包含: –

 <script src="ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script> 

第三 – 在组件ts写这个代码: –

  import {ResponseContentType} from '@angular.core'; let headers = new Headers({ 'Content-Type': 'application/json', 'MyApp-Application' : 'AppName', 'Accept': 'application/pdf' }); let options = new RequestOptions({ headers: headers, responseType: ResponseContentType.Blob }); this.http .post('/project/test/export', somevalue,options) .subscribe(data => { var mediaType = 'application/vnd.ms-excel'; let blob: Blob = data.blob(); window['saveAs'](blob, 'sample.xls'); }); 

这将给你xls文件格式…如果你想要其他格式,请更改mediatype和文件名正确的扩展…谢谢你希望它可以帮助….

对于那些使用Redux模式

我在文件保护程序中添加了@Hector Cuevas的名字。 使用Angular2 v 2.3.1,我不需要添加@ types / file-saver。

以下示例是以PDF格式下载日志。

期刊行为

 public static DOWNLOAD_JOURNALS = '[Journals] Download as PDF'; public downloadJournals(referenceId: string): Action { return { type: JournalActions.DOWNLOAD_JOURNALS, payload: { referenceId: referenceId } }; } public static DOWNLOAD_JOURNALS_SUCCESS = '[Journals] Download as PDF Success'; public downloadJournalsSuccess(blob: Blob): Action { return { type: JournalActions.DOWNLOAD_JOURNALS_SUCCESS, payload: { blob: blob } }; } 

期刊效应

 @Effect() download$ = this.actions$ .ofType(JournalActions.DOWNLOAD_JOURNALS) .switchMap(({payload}) => this._journalApiService.downloadJournal(payload.referenceId) .map((blob) => this._actions.downloadJournalsSuccess(blob)) .catch((err) => handleError(err, this._actions.downloadJournalsFail(err))) ); @Effect() downloadJournalSuccess$ = this.actions$ .ofType(JournalActions.DOWNLOAD_JOURNALS_SUCCESS) .map(({payload}) => saveBlobAs(payload.blob, 'journal.pdf')) 

期刊服务

 public downloadJournal(referenceId: string): Observable<any> { const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`; return this._http.getBlob(url); } 

HTTP服务

 public getBlob = (url: string): Observable<any> => { return this.request({ method: RequestMethod.Get, url: url, responseType: ResponseContentType.Blob }); }; 

日志减速器 虽然这只是设置我们的应用程序中使用的正确的状态,我仍然想要添加它来显示完整的模式。

 case JournalActions.DOWNLOAD_JOURNALS: { return Object.assign({}, state, <IJournalState>{ downloading: true, hasValidationErrors: false, errors: [] }); } case JournalActions.DOWNLOAD_JOURNALS_SUCCESS: { return Object.assign({}, state, <IJournalState>{ downloading: false, hasValidationErrors: false, errors: [] }); } 

我希望这是有帮助的。

要下载和显示PDF文件,一个非常类似的代码片断如下所示:

  private downloadFile(data: Response): void { let blob = new Blob([data.blob()], { type: "application/pdf" }); let url = window.URL.createObjectURL(blob); window.open(url); } public showFile(fileEndpointPath: string): void { let reqOpt: RequestOptions = this.getAcmOptions(); // getAcmOptions is our helper method. Change this line according to request headers you need. reqOpt.responseType = ResponseContentType.Blob; this.http .get(fileEndpointPath, reqOpt) .subscribe( data => this.downloadFile(data), error => alert("Error downloading file!"), () => console.log("OK!") ); }