How do I download a file with Angular2
up vote
93
down vote
favorite
I have a WebApi / MVC app for which I am developing an angular2 client (to replace MVC). I am having some troubles understanding how Angular saves a file.
The request is ok (works fine with MVC, and we can log the data received) but I can't figure out how to save the downloaded data (I am mostly following the same logic as in this post). I am sure it is stupidly simple, but so far I am simply not grasping it.
The code of the component function is below. I've tried different alternatives, the blob way should be the way to go as far as I understood, but there is no function createObjectURL
in URL
. I can't even find the definition of URL
in window, but apparently it exists. If I use the FileSaver.js
module I get the same error. So I guess this is something that changed recently or is not yet implemented. How can I trigger the file save in 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);
}
For the sake of completeness, the service that fetches the data is below, but the only thing it does is to issue the request and pass on the data without mapping if it succeeds:
downloadfile(runname: string, type: string){
return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
.catch(this.logAndPassOn);
}
angular typescript download fileapi
add a comment |
up vote
93
down vote
favorite
I have a WebApi / MVC app for which I am developing an angular2 client (to replace MVC). I am having some troubles understanding how Angular saves a file.
The request is ok (works fine with MVC, and we can log the data received) but I can't figure out how to save the downloaded data (I am mostly following the same logic as in this post). I am sure it is stupidly simple, but so far I am simply not grasping it.
The code of the component function is below. I've tried different alternatives, the blob way should be the way to go as far as I understood, but there is no function createObjectURL
in URL
. I can't even find the definition of URL
in window, but apparently it exists. If I use the FileSaver.js
module I get the same error. So I guess this is something that changed recently or is not yet implemented. How can I trigger the file save in 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);
}
For the sake of completeness, the service that fetches the data is below, but the only thing it does is to issue the request and pass on the data without mapping if it succeeds:
downloadfile(runname: string, type: string){
return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
.catch(this.logAndPassOn);
}
angular typescript download fileapi
add a comment |
up vote
93
down vote
favorite
up vote
93
down vote
favorite
I have a WebApi / MVC app for which I am developing an angular2 client (to replace MVC). I am having some troubles understanding how Angular saves a file.
The request is ok (works fine with MVC, and we can log the data received) but I can't figure out how to save the downloaded data (I am mostly following the same logic as in this post). I am sure it is stupidly simple, but so far I am simply not grasping it.
The code of the component function is below. I've tried different alternatives, the blob way should be the way to go as far as I understood, but there is no function createObjectURL
in URL
. I can't even find the definition of URL
in window, but apparently it exists. If I use the FileSaver.js
module I get the same error. So I guess this is something that changed recently or is not yet implemented. How can I trigger the file save in 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);
}
For the sake of completeness, the service that fetches the data is below, but the only thing it does is to issue the request and pass on the data without mapping if it succeeds:
downloadfile(runname: string, type: string){
return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
.catch(this.logAndPassOn);
}
angular typescript download fileapi
I have a WebApi / MVC app for which I am developing an angular2 client (to replace MVC). I am having some troubles understanding how Angular saves a file.
The request is ok (works fine with MVC, and we can log the data received) but I can't figure out how to save the downloaded data (I am mostly following the same logic as in this post). I am sure it is stupidly simple, but so far I am simply not grasping it.
The code of the component function is below. I've tried different alternatives, the blob way should be the way to go as far as I understood, but there is no function createObjectURL
in URL
. I can't even find the definition of URL
in window, but apparently it exists. If I use the FileSaver.js
module I get the same error. So I guess this is something that changed recently or is not yet implemented. How can I trigger the file save in 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);
}
For the sake of completeness, the service that fetches the data is below, but the only thing it does is to issue the request and pass on the data without mapping if it succeeds:
downloadfile(runname: string, type: string){
return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
.catch(this.logAndPassOn);
}
angular typescript download fileapi
angular typescript download fileapi
edited Nov 27 at 15:41
E_net4 is kind and welcoming
11.6k63468
11.6k63468
asked Feb 1 '16 at 19:15
rll
2,69022042
2,69022042
add a comment |
add a comment |
19 Answers
19
active
oldest
votes
up vote
101
down vote
accepted
the problem is that the observable run in another context, so when you try to create the URL var you have an empty object and not the blob you want.
One of the many ways that exist to solve this , is as follows:
this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
error => console.log('Error downloading the file.'),
() => console.info('OK');
When the request is ready it will call the function "downloadFile" that is defined as follows:
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
the blob has been created perfectly and so the URL var, if doesn't open the new window please check that you have already imported 'rxjs/Rx' ;
import 'rxjs/Rx' ;
hope this can help you.
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
What isthis._reportService.getReport()
and what does it return?
– Burjua
Aug 15 '17 at 16:37
1
@Burjua thegetReport()
returns athis.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
|
show 2 more comments
up vote
56
down vote
Try this!
1 - Install dependencies for show save/open file pop-up
npm install file-saver --save
npm install @types/file-saver --save
2- Create a service with this function to recive the data
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- In the component parse the blob with 'file-saver'
import {saveAs as importedSaveAs} from "file-saver";
this.myService.downloadFile(this.id).subscribe(blob => {
importedSaveAs(blob, this.fileName);
}
)
This works for me!
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
add a comment |
up vote
18
down vote
If you don't need to add headers in the request, to download a file in Angular2 you can do a simple:
window.location.href='http://example.com/myuri/report?param=x';
in your component.
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he usesauthHttp
!
– A.Akram
Apr 17 '17 at 10:50
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
add a comment |
up vote
15
down vote
As mentioned by Alejandro Corredor it is a simple scope error. The subscribe
is run asynchronously and the open
must be placed in that context, so that the data finished loading when we trigger the download.
That said, there are two ways of doing it. As the docs recommend the service takes care of getting and mapping the data:
//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);
}
Then, on the component we just subscribe and deal with the mapped data. There are two possibilities. The first, as suggested in the original post, but needs a small correction as noted by 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.'));
}
The second way would be to use FileReader. The logic is the same but we can explicitly wait for FileReader to load the data, avoiding the nesting, and solving the async problem.
//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');
}
}
Note: I am trying to download an Excel file, and even though the download is triggered (so this answers the question), the file is corrupt. See the answer to this post for avoiding the corrupt file.
6
I think the reason the file gets corrupted is because you are loadingres
into the blob and you actually wantres._body
. However_body
is a private variable and not accessible. As of today.blob()
and.arrayBuffer()
on a http response object have not been implemented in Angular 2.text()
andjson()
are the only two options but both will garble your body. Have you found a solution?
– sschueller
Mar 18 '16 at 14:05
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
My solution is to just use<a href=""></a>
to download a file.
– user2061057
Jan 2 '17 at 14:35
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
|
show 11 more comments
up vote
14
down vote
Download *.zip solution for angular 2.4.x: you must import ResponseContentType from '@angular/http' and change responseType to ResponseContentType.ArrayBuffer (by default it 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']);
}
add a comment |
up vote
13
down vote
This is for folks looking how to do it using HttpClient and file-saver:
- Install file-saver
npm install file-saver --save
npm install @types/file-saver --save
API Service class:
export() {
return this.http.get(this.download_endpoint,
{responseType: 'blob'});
}
Component:
import { saveAs } from 'file-saver';
exportPdf() {
this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
add a comment |
up vote
11
down vote
How about this?
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();
})
I could do with it.
no need additional package.
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
add a comment |
up vote
8
down vote
Downloading file through ajax is always a painful process and In my view it is best to let server and browser do this work of content type negotiation.
I think its best to have
<a href="api/sample/download"></a>
to do it. This doesn't even require any new windows opening and stuff like that.
The MVC controller as in your sample can be like the one below:
[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
// ...
return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
add a comment |
up vote
5
down vote
For newer angular versions:
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');
});
add a comment |
up vote
4
down vote
For those using Redux Pattern
I added in the file-saver as @Hector Cuevas named in his answer. Using Angular2 v. 2.3.1, I didn't need to add in the @types/file-saver.
The following example is to download a journal as PDF.
The journal actions
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 }
};
}
The journal effects
@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'))
The journal service
public downloadJournal(referenceId: string): Observable<any> {
const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
return this._http.getBlob(url);
}
The HTTP service
public getBlob = (url: string): Observable<any> => {
return this.request({
method: RequestMethod.Get,
url: url,
responseType: ResponseContentType.Blob
});
};
The journal reducer
Though this only sets the correct states used in our application I still wanted to add it in to show the complete pattern.
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: });
}
I hope this is helpful.
add a comment |
up vote
4
down vote
I share the solution that helped me (any improvement is greatly appreciated)
On your service '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'));
}
Component Part :
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);
}
On the component part, you call the service without subscribing to a response. The subscribe
for a complete list of openOffice mime types see : http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
add a comment |
up vote
3
down vote
To download and show PDF files, a very similar code snipped is like below:
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!")
);
}
add a comment |
up vote
2
down vote
I am using Angular 4 with the 4.3 httpClient object. I modified an answer I found in Js' Technical Blog which creates a link object, uses it to do the download, then destroys it.
Client:
doDownload(id: number, contentType: string) {
return this.http
.get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}
downloadFile(id: number, contentType: string, filename:string) {
return this.doDownload(id, contentType).subscribe(
res => {
var url = window.URL.createObjectURL(res);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove(); // remove the element
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.')
});
}
The value of this.downloadUrl has been set previously to point to the api. I am using this to download attachments, so I know the id, contentType and filename:
I am using an MVC api to return the file:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public FileContentResult GetAttachment(Int32 attachmentID)
{
Attachment AT = filerep.GetAttachment(attachmentID);
if (AT != null)
{
return new FileContentResult(AT.FileBytes, AT.ContentType);
}
else
{
return null;
}
}
The attachment class looks like this:
public class Attachment
{
public Int32 AttachmentID { get; set; }
public string FileName { get; set; }
public byte FileBytes { get; set; }
public string ContentType { get; set; }
}
The filerep repository returns the file from the database.
Hope this helps someone :)
add a comment |
up vote
2
down vote
Update to Hector's answer using file-saver and HttpClient for step 2:
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
add a comment |
up vote
2
down vote
Here's something I did in my case -
// 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"));
}
The solution is referenced from - here
add a comment |
up vote
1
down vote
I got a solution for downloading from angular 2 without getting corrupt,
using spring mvc and angular 2
1st- my return type is :-ResponseEntity from java end. Here I am sending byte array has return type from the controller.
2nd- to include the filesaver in your workspace-in the index page as:
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
3rd- at component ts write this code:
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');
});
This will give you xls file format. If you want other formats change the mediatype and file name with right extension.
add a comment |
up vote
0
down vote
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();
});
add a comment |
up vote
0
down vote
It will be better if you try to call the new method inside you subscribe
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => onsole.log(error),
() => console.log('Complete')
);
Inside downloadFile(data)
function we need to make block, link, href and file name
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);
}
}
add a comment |
up vote
0
down vote
Simply put the url
as href
as below .
<a href="my_url">Download File</a>
add a comment |
19 Answers
19
active
oldest
votes
19 Answers
19
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
101
down vote
accepted
the problem is that the observable run in another context, so when you try to create the URL var you have an empty object and not the blob you want.
One of the many ways that exist to solve this , is as follows:
this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
error => console.log('Error downloading the file.'),
() => console.info('OK');
When the request is ready it will call the function "downloadFile" that is defined as follows:
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
the blob has been created perfectly and so the URL var, if doesn't open the new window please check that you have already imported 'rxjs/Rx' ;
import 'rxjs/Rx' ;
hope this can help you.
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
What isthis._reportService.getReport()
and what does it return?
– Burjua
Aug 15 '17 at 16:37
1
@Burjua thegetReport()
returns athis.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
|
show 2 more comments
up vote
101
down vote
accepted
the problem is that the observable run in another context, so when you try to create the URL var you have an empty object and not the blob you want.
One of the many ways that exist to solve this , is as follows:
this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
error => console.log('Error downloading the file.'),
() => console.info('OK');
When the request is ready it will call the function "downloadFile" that is defined as follows:
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
the blob has been created perfectly and so the URL var, if doesn't open the new window please check that you have already imported 'rxjs/Rx' ;
import 'rxjs/Rx' ;
hope this can help you.
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
What isthis._reportService.getReport()
and what does it return?
– Burjua
Aug 15 '17 at 16:37
1
@Burjua thegetReport()
returns athis.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
|
show 2 more comments
up vote
101
down vote
accepted
up vote
101
down vote
accepted
the problem is that the observable run in another context, so when you try to create the URL var you have an empty object and not the blob you want.
One of the many ways that exist to solve this , is as follows:
this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
error => console.log('Error downloading the file.'),
() => console.info('OK');
When the request is ready it will call the function "downloadFile" that is defined as follows:
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
the blob has been created perfectly and so the URL var, if doesn't open the new window please check that you have already imported 'rxjs/Rx' ;
import 'rxjs/Rx' ;
hope this can help you.
the problem is that the observable run in another context, so when you try to create the URL var you have an empty object and not the blob you want.
One of the many ways that exist to solve this , is as follows:
this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
error => console.log('Error downloading the file.'),
() => console.info('OK');
When the request is ready it will call the function "downloadFile" that is defined as follows:
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
the blob has been created perfectly and so the URL var, if doesn't open the new window please check that you have already imported 'rxjs/Rx' ;
import 'rxjs/Rx' ;
hope this can help you.
edited Nov 16 at 18:44
Derek J.
400415
400415
answered Feb 4 '16 at 19:54
Alejandro Corredor
1,044156
1,044156
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
What isthis._reportService.getReport()
and what does it return?
– Burjua
Aug 15 '17 at 16:37
1
@Burjua thegetReport()
returns athis.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
|
show 2 more comments
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
What isthis._reportService.getReport()
and what does it return?
– Burjua
Aug 15 '17 at 16:37
1
@Burjua thegetReport()
returns athis.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
Will it work to download zip file also ? I have application/octet-stream as response from java REST service which accepts custom headers.I want to download that as zip file. Any Idea ?
– Techno Cracker
Jul 25 '17 at 9:35
4
4
What is
this._reportService.getReport()
and what does it return?– Burjua
Aug 15 '17 at 16:37
What is
this._reportService.getReport()
and what does it return?– Burjua
Aug 15 '17 at 16:37
1
1
@Burjua the
getReport()
returns a this.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@Burjua the
getReport()
returns a this.http.get(PriceConf.download.url)
– ji-ruh
Sep 4 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
@michalzfania you can implement it like this: stackoverflow.com/a/19328891/790635
– emp
Nov 22 '17 at 8:55
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
The problem I have is that after windows downloads the file, it doesn't recognize it's format. For example there is no .csv at the end of the file, though the file content was saved correctly.
– Benjamin
Jun 29 at 7:05
|
show 2 more comments
up vote
56
down vote
Try this!
1 - Install dependencies for show save/open file pop-up
npm install file-saver --save
npm install @types/file-saver --save
2- Create a service with this function to recive the data
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- In the component parse the blob with 'file-saver'
import {saveAs as importedSaveAs} from "file-saver";
this.myService.downloadFile(this.id).subscribe(blob => {
importedSaveAs(blob, this.fileName);
}
)
This works for me!
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
add a comment |
up vote
56
down vote
Try this!
1 - Install dependencies for show save/open file pop-up
npm install file-saver --save
npm install @types/file-saver --save
2- Create a service with this function to recive the data
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- In the component parse the blob with 'file-saver'
import {saveAs as importedSaveAs} from "file-saver";
this.myService.downloadFile(this.id).subscribe(blob => {
importedSaveAs(blob, this.fileName);
}
)
This works for me!
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
add a comment |
up vote
56
down vote
up vote
56
down vote
Try this!
1 - Install dependencies for show save/open file pop-up
npm install file-saver --save
npm install @types/file-saver --save
2- Create a service with this function to recive the data
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- In the component parse the blob with 'file-saver'
import {saveAs as importedSaveAs} from "file-saver";
this.myService.downloadFile(this.id).subscribe(blob => {
importedSaveAs(blob, this.fileName);
}
)
This works for me!
Try this!
1 - Install dependencies for show save/open file pop-up
npm install file-saver --save
npm install @types/file-saver --save
2- Create a service with this function to recive the data
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- In the component parse the blob with 'file-saver'
import {saveAs as importedSaveAs} from "file-saver";
this.myService.downloadFile(this.id).subscribe(blob => {
importedSaveAs(blob, this.fileName);
}
)
This works for me!
edited May 17 at 12:05
Frederik Struck-Schøning
9,69774151
9,69774151
answered May 11 '17 at 10:24
Hector Cuevas
57733
57733
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
add a comment |
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
I used step 2 in combination with the answer from @Alejandro and it worked without the need to install file-saver...
– Ewert
Mar 13 at 11:11
3
3
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
Thank you! It works perfectly! I wonder if we can get the filename that is defined on the header of the response. Is that possible?
– jfajunior
Mar 26 at 9:41
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
it solved my problem !! thanks
– Abhijeet
Oct 9 at 8:51
1
1
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
error Av5 Argument of type 'RequestOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string; };
– Hemanth SP
Nov 16 at 8:35
add a comment |
up vote
18
down vote
If you don't need to add headers in the request, to download a file in Angular2 you can do a simple:
window.location.href='http://example.com/myuri/report?param=x';
in your component.
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he usesauthHttp
!
– A.Akram
Apr 17 '17 at 10:50
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
add a comment |
up vote
18
down vote
If you don't need to add headers in the request, to download a file in Angular2 you can do a simple:
window.location.href='http://example.com/myuri/report?param=x';
in your component.
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he usesauthHttp
!
– A.Akram
Apr 17 '17 at 10:50
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
add a comment |
up vote
18
down vote
up vote
18
down vote
If you don't need to add headers in the request, to download a file in Angular2 you can do a simple:
window.location.href='http://example.com/myuri/report?param=x';
in your component.
If you don't need to add headers in the request, to download a file in Angular2 you can do a simple:
window.location.href='http://example.com/myuri/report?param=x';
in your component.
edited May 18 at 7:13
Frederik Struck-Schøning
9,69774151
9,69774151
answered Aug 4 '16 at 5:37
surfealokesea
2,44111829
2,44111829
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he usesauthHttp
!
– A.Akram
Apr 17 '17 at 10:50
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
add a comment |
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he usesauthHttp
!
– A.Akram
Apr 17 '17 at 10:50
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
1
1
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
Can someone please tell why this answer is downvoted? The topic is to download a file using angular2. If this method works to do a simple download then it should also be marked as a valid answer.
– Saurabh Shetty
Feb 15 '17 at 18:37
4
4
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he uses
authHttp
!– A.Akram
Apr 17 '17 at 10:50
@SaurabhShetty, This won't help in case you want to send custom headers, what if you want to send an auth token for example? If you look into OP question you can see he uses
authHttp
!– A.Akram
Apr 17 '17 at 10:50
2
2
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
I do understand the downvotes, nevertheless this answer solved my issue.
– JoeriShoeby
Apr 21 '17 at 13:06
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
If you let the server return the url in some context, the server could prepare the url. ex: object: MyRecord.Cover. The cover could be a url to an image in the server. When calling get(Myrecord) you let the server return the prepared url (Cover), with security token and other headers set.
– Jens Alenius
Oct 23 '17 at 13:26
add a comment |
up vote
15
down vote
As mentioned by Alejandro Corredor it is a simple scope error. The subscribe
is run asynchronously and the open
must be placed in that context, so that the data finished loading when we trigger the download.
That said, there are two ways of doing it. As the docs recommend the service takes care of getting and mapping the data:
//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);
}
Then, on the component we just subscribe and deal with the mapped data. There are two possibilities. The first, as suggested in the original post, but needs a small correction as noted by 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.'));
}
The second way would be to use FileReader. The logic is the same but we can explicitly wait for FileReader to load the data, avoiding the nesting, and solving the async problem.
//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');
}
}
Note: I am trying to download an Excel file, and even though the download is triggered (so this answers the question), the file is corrupt. See the answer to this post for avoiding the corrupt file.
6
I think the reason the file gets corrupted is because you are loadingres
into the blob and you actually wantres._body
. However_body
is a private variable and not accessible. As of today.blob()
and.arrayBuffer()
on a http response object have not been implemented in Angular 2.text()
andjson()
are the only two options but both will garble your body. Have you found a solution?
– sschueller
Mar 18 '16 at 14:05
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
My solution is to just use<a href=""></a>
to download a file.
– user2061057
Jan 2 '17 at 14:35
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
|
show 11 more comments
up vote
15
down vote
As mentioned by Alejandro Corredor it is a simple scope error. The subscribe
is run asynchronously and the open
must be placed in that context, so that the data finished loading when we trigger the download.
That said, there are two ways of doing it. As the docs recommend the service takes care of getting and mapping the data:
//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);
}
Then, on the component we just subscribe and deal with the mapped data. There are two possibilities. The first, as suggested in the original post, but needs a small correction as noted by 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.'));
}
The second way would be to use FileReader. The logic is the same but we can explicitly wait for FileReader to load the data, avoiding the nesting, and solving the async problem.
//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');
}
}
Note: I am trying to download an Excel file, and even though the download is triggered (so this answers the question), the file is corrupt. See the answer to this post for avoiding the corrupt file.
6
I think the reason the file gets corrupted is because you are loadingres
into the blob and you actually wantres._body
. However_body
is a private variable and not accessible. As of today.blob()
and.arrayBuffer()
on a http response object have not been implemented in Angular 2.text()
andjson()
are the only two options but both will garble your body. Have you found a solution?
– sschueller
Mar 18 '16 at 14:05
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
My solution is to just use<a href=""></a>
to download a file.
– user2061057
Jan 2 '17 at 14:35
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
|
show 11 more comments
up vote
15
down vote
up vote
15
down vote
As mentioned by Alejandro Corredor it is a simple scope error. The subscribe
is run asynchronously and the open
must be placed in that context, so that the data finished loading when we trigger the download.
That said, there are two ways of doing it. As the docs recommend the service takes care of getting and mapping the data:
//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);
}
Then, on the component we just subscribe and deal with the mapped data. There are two possibilities. The first, as suggested in the original post, but needs a small correction as noted by 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.'));
}
The second way would be to use FileReader. The logic is the same but we can explicitly wait for FileReader to load the data, avoiding the nesting, and solving the async problem.
//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');
}
}
Note: I am trying to download an Excel file, and even though the download is triggered (so this answers the question), the file is corrupt. See the answer to this post for avoiding the corrupt file.
As mentioned by Alejandro Corredor it is a simple scope error. The subscribe
is run asynchronously and the open
must be placed in that context, so that the data finished loading when we trigger the download.
That said, there are two ways of doing it. As the docs recommend the service takes care of getting and mapping the data:
//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);
}
Then, on the component we just subscribe and deal with the mapped data. There are two possibilities. The first, as suggested in the original post, but needs a small correction as noted by 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.'));
}
The second way would be to use FileReader. The logic is the same but we can explicitly wait for FileReader to load the data, avoiding the nesting, and solving the async problem.
//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');
}
}
Note: I am trying to download an Excel file, and even though the download is triggered (so this answers the question), the file is corrupt. See the answer to this post for avoiding the corrupt file.
edited May 17 at 12:09
Frederik Struck-Schøning
9,69774151
9,69774151
answered Feb 5 '16 at 15:35
rll
2,69022042
2,69022042
6
I think the reason the file gets corrupted is because you are loadingres
into the blob and you actually wantres._body
. However_body
is a private variable and not accessible. As of today.blob()
and.arrayBuffer()
on a http response object have not been implemented in Angular 2.text()
andjson()
are the only two options but both will garble your body. Have you found a solution?
– sschueller
Mar 18 '16 at 14:05
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
My solution is to just use<a href=""></a>
to download a file.
– user2061057
Jan 2 '17 at 14:35
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
|
show 11 more comments
6
I think the reason the file gets corrupted is because you are loadingres
into the blob and you actually wantres._body
. However_body
is a private variable and not accessible. As of today.blob()
and.arrayBuffer()
on a http response object have not been implemented in Angular 2.text()
andjson()
are the only two options but both will garble your body. Have you found a solution?
– sschueller
Mar 18 '16 at 14:05
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
My solution is to just use<a href=""></a>
to download a file.
– user2061057
Jan 2 '17 at 14:35
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
6
6
I think the reason the file gets corrupted is because you are loading
res
into the blob and you actually want res._body
. However _body
is a private variable and not accessible. As of today .blob()
and .arrayBuffer()
on a http response object have not been implemented in Angular 2. text()
and json()
are the only two options but both will garble your body. Have you found a solution?– sschueller
Mar 18 '16 at 14:05
I think the reason the file gets corrupted is because you are loading
res
into the blob and you actually want res._body
. However _body
is a private variable and not accessible. As of today .blob()
and .arrayBuffer()
on a http response object have not been implemented in Angular 2. text()
and json()
are the only two options but both will garble your body. Have you found a solution?– sschueller
Mar 18 '16 at 14:05
1
1
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
hi @rll, i followed the above steps and i am getting subscribe as completed. Still i couldn't see the file getting downloaded. I couldn't see any error as well. Please help
– AishApp
May 4 '16 at 13:40
1
1
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
The 2 options lets me download the file, but it loads the data in the background first. What if I have a large file that has to be downloaded?
– f123
Nov 4 '16 at 6:30
1
1
My solution is to just use
<a href=""></a>
to download a file.– user2061057
Jan 2 '17 at 14:35
My solution is to just use
<a href=""></a>
to download a file.– user2061057
Jan 2 '17 at 14:35
1
1
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
I know this is an old answer but it's high up on search results and is the accepted answer: The line ` headers.append('responseType', 'arraybuffer');` is wrong. It's an option, not a header. Please fix it. Aaaand... The headers are created and not used. Not helpful.
– Stevo
Apr 21 '17 at 13:54
|
show 11 more comments
up vote
14
down vote
Download *.zip solution for angular 2.4.x: you must import ResponseContentType from '@angular/http' and change responseType to ResponseContentType.ArrayBuffer (by default it 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']);
}
add a comment |
up vote
14
down vote
Download *.zip solution for angular 2.4.x: you must import ResponseContentType from '@angular/http' and change responseType to ResponseContentType.ArrayBuffer (by default it 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']);
}
add a comment |
up vote
14
down vote
up vote
14
down vote
Download *.zip solution for angular 2.4.x: you must import ResponseContentType from '@angular/http' and change responseType to ResponseContentType.ArrayBuffer (by default it 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']);
}
Download *.zip solution for angular 2.4.x: you must import ResponseContentType from '@angular/http' and change responseType to ResponseContentType.ArrayBuffer (by default it 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']);
}
edited May 17 at 12:07
Frederik Struck-Schøning
9,69774151
9,69774151
answered Feb 12 '17 at 14:58
Alex Dzeiko
58179
58179
add a comment |
add a comment |
up vote
13
down vote
This is for folks looking how to do it using HttpClient and file-saver:
- Install file-saver
npm install file-saver --save
npm install @types/file-saver --save
API Service class:
export() {
return this.http.get(this.download_endpoint,
{responseType: 'blob'});
}
Component:
import { saveAs } from 'file-saver';
exportPdf() {
this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
add a comment |
up vote
13
down vote
This is for folks looking how to do it using HttpClient and file-saver:
- Install file-saver
npm install file-saver --save
npm install @types/file-saver --save
API Service class:
export() {
return this.http.get(this.download_endpoint,
{responseType: 'blob'});
}
Component:
import { saveAs } from 'file-saver';
exportPdf() {
this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
add a comment |
up vote
13
down vote
up vote
13
down vote
This is for folks looking how to do it using HttpClient and file-saver:
- Install file-saver
npm install file-saver --save
npm install @types/file-saver --save
API Service class:
export() {
return this.http.get(this.download_endpoint,
{responseType: 'blob'});
}
Component:
import { saveAs } from 'file-saver';
exportPdf() {
this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}
This is for folks looking how to do it using HttpClient and file-saver:
- Install file-saver
npm install file-saver --save
npm install @types/file-saver --save
API Service class:
export() {
return this.http.get(this.download_endpoint,
{responseType: 'blob'});
}
Component:
import { saveAs } from 'file-saver';
exportPdf() {
this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}
edited May 18 at 7:15
Frederik Struck-Schøning
9,69774151
9,69774151
answered Jan 29 at 14:13
Justin
38039
38039
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
add a comment |
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
This should be voted higher. Easy and works flawlessly
– Jakob Fischer
Nov 1 at 12:18
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
How to show the filesize in the browser when the download starts? I am sending the filesize as content-length in the http header.
– humbleCoder
yesterday
add a comment |
up vote
11
down vote
How about this?
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();
})
I could do with it.
no need additional package.
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
add a comment |
up vote
11
down vote
How about this?
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();
})
I could do with it.
no need additional package.
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
add a comment |
up vote
11
down vote
up vote
11
down vote
How about this?
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();
})
I could do with it.
no need additional package.
How about this?
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();
})
I could do with it.
no need additional package.
edited May 17 at 12:06
Frederik Struck-Schøning
9,69774151
9,69774151
answered Jul 13 '17 at 0:28
harufumi.abe
13927
13927
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
add a comment |
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
1
1
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
So simple yet it is the one that work flawlessly. It doesn't clutter the DOM, doesn't create any element. I combined this solution with some of the aboves and it works like a charm.
– Chax
Nov 1 at 14:33
add a comment |
up vote
8
down vote
Downloading file through ajax is always a painful process and In my view it is best to let server and browser do this work of content type negotiation.
I think its best to have
<a href="api/sample/download"></a>
to do it. This doesn't even require any new windows opening and stuff like that.
The MVC controller as in your sample can be like the one below:
[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
// ...
return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
add a comment |
up vote
8
down vote
Downloading file through ajax is always a painful process and In my view it is best to let server and browser do this work of content type negotiation.
I think its best to have
<a href="api/sample/download"></a>
to do it. This doesn't even require any new windows opening and stuff like that.
The MVC controller as in your sample can be like the one below:
[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
// ...
return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
add a comment |
up vote
8
down vote
up vote
8
down vote
Downloading file through ajax is always a painful process and In my view it is best to let server and browser do this work of content type negotiation.
I think its best to have
<a href="api/sample/download"></a>
to do it. This doesn't even require any new windows opening and stuff like that.
The MVC controller as in your sample can be like the one below:
[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
// ...
return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}
Downloading file through ajax is always a painful process and In my view it is best to let server and browser do this work of content type negotiation.
I think its best to have
<a href="api/sample/download"></a>
to do it. This doesn't even require any new windows opening and stuff like that.
The MVC controller as in your sample can be like the one below:
[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
// ...
return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}
edited Aug 3 at 1:24
Massimiliano Kraus
2,33741532
2,33741532
answered Jan 20 '17 at 5:13
Bharat Raj
17914
17914
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
add a comment |
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
1
1
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
You're right, but then how can you manage server errors within the single-page application? In case of an error, normally, a REST service returns the JSON with the error, thus resulting the application to open the JSON in another browser window, which is not what the user wants to see
– Luca
Apr 4 '17 at 13:01
2
2
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
If you have an access token you need to provide this doesn't work
– chris31389
Sep 20 '17 at 16:15
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
This is plain and simple. But if you wanna do some authentication, then there is a possibility of having something like a one time token. So, instead of having it like this, you can have the url as: example.com/myuri/report?tokenid=1234-1233 And verify the token ID in the database. Of course its not a simple scenario and works in all the situations, but can be a solution in situation where, you have access to the database before returning the report as a stream..
– Bharat Raj
Sep 22 '17 at 9:59
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
Get the download url from the server. So the server can prepare the url with onetime security token.
– Jens Alenius
Oct 23 '17 at 13:23
add a comment |
up vote
5
down vote
For newer angular versions:
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');
});
add a comment |
up vote
5
down vote
For newer angular versions:
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');
});
add a comment |
up vote
5
down vote
up vote
5
down vote
For newer angular versions:
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');
});
For newer angular versions:
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');
});
answered Jun 29 at 15:33
Tobias Ernst
673710
673710
add a comment |
add a comment |
up vote
4
down vote
For those using Redux Pattern
I added in the file-saver as @Hector Cuevas named in his answer. Using Angular2 v. 2.3.1, I didn't need to add in the @types/file-saver.
The following example is to download a journal as PDF.
The journal actions
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 }
};
}
The journal effects
@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'))
The journal service
public downloadJournal(referenceId: string): Observable<any> {
const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
return this._http.getBlob(url);
}
The HTTP service
public getBlob = (url: string): Observable<any> => {
return this.request({
method: RequestMethod.Get,
url: url,
responseType: ResponseContentType.Blob
});
};
The journal reducer
Though this only sets the correct states used in our application I still wanted to add it in to show the complete pattern.
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: });
}
I hope this is helpful.
add a comment |
up vote
4
down vote
For those using Redux Pattern
I added in the file-saver as @Hector Cuevas named in his answer. Using Angular2 v. 2.3.1, I didn't need to add in the @types/file-saver.
The following example is to download a journal as PDF.
The journal actions
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 }
};
}
The journal effects
@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'))
The journal service
public downloadJournal(referenceId: string): Observable<any> {
const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
return this._http.getBlob(url);
}
The HTTP service
public getBlob = (url: string): Observable<any> => {
return this.request({
method: RequestMethod.Get,
url: url,
responseType: ResponseContentType.Blob
});
};
The journal reducer
Though this only sets the correct states used in our application I still wanted to add it in to show the complete pattern.
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: });
}
I hope this is helpful.
add a comment |
up vote
4
down vote
up vote
4
down vote
For those using Redux Pattern
I added in the file-saver as @Hector Cuevas named in his answer. Using Angular2 v. 2.3.1, I didn't need to add in the @types/file-saver.
The following example is to download a journal as PDF.
The journal actions
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 }
};
}
The journal effects
@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'))
The journal service
public downloadJournal(referenceId: string): Observable<any> {
const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
return this._http.getBlob(url);
}
The HTTP service
public getBlob = (url: string): Observable<any> => {
return this.request({
method: RequestMethod.Get,
url: url,
responseType: ResponseContentType.Blob
});
};
The journal reducer
Though this only sets the correct states used in our application I still wanted to add it in to show the complete pattern.
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: });
}
I hope this is helpful.
For those using Redux Pattern
I added in the file-saver as @Hector Cuevas named in his answer. Using Angular2 v. 2.3.1, I didn't need to add in the @types/file-saver.
The following example is to download a journal as PDF.
The journal actions
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 }
};
}
The journal effects
@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'))
The journal service
public downloadJournal(referenceId: string): Observable<any> {
const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
return this._http.getBlob(url);
}
The HTTP service
public getBlob = (url: string): Observable<any> => {
return this.request({
method: RequestMethod.Get,
url: url,
responseType: ResponseContentType.Blob
});
};
The journal reducer
Though this only sets the correct states used in our application I still wanted to add it in to show the complete pattern.
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: });
}
I hope this is helpful.
edited May 17 at 12:05
Frederik Struck-Schøning
9,69774151
9,69774151
answered Aug 17 '17 at 9:01
Casper Nybroe
2191522
2191522
add a comment |
add a comment |
up vote
4
down vote
I share the solution that helped me (any improvement is greatly appreciated)
On your service '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'));
}
Component Part :
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);
}
On the component part, you call the service without subscribing to a response. The subscribe
for a complete list of openOffice mime types see : http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
add a comment |
up vote
4
down vote
I share the solution that helped me (any improvement is greatly appreciated)
On your service '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'));
}
Component Part :
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);
}
On the component part, you call the service without subscribing to a response. The subscribe
for a complete list of openOffice mime types see : http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
add a comment |
up vote
4
down vote
up vote
4
down vote
I share the solution that helped me (any improvement is greatly appreciated)
On your service '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'));
}
Component Part :
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);
}
On the component part, you call the service without subscribing to a response. The subscribe
for a complete list of openOffice mime types see : http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
I share the solution that helped me (any improvement is greatly appreciated)
On your service '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'));
}
Component Part :
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);
}
On the component part, you call the service without subscribing to a response. The subscribe
for a complete list of openOffice mime types see : http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
edited May 17 at 12:10
Frederik Struck-Schøning
9,69774151
9,69774151
answered Jan 18 '17 at 14:16
Ismail H
1,18811232
1,18811232
add a comment |
add a comment |
up vote
3
down vote
To download and show PDF files, a very similar code snipped is like below:
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!")
);
}
add a comment |
up vote
3
down vote
To download and show PDF files, a very similar code snipped is like below:
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!")
);
}
add a comment |
up vote
3
down vote
up vote
3
down vote
To download and show PDF files, a very similar code snipped is like below:
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!")
);
}
To download and show PDF files, a very similar code snipped is like below:
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!")
);
}
edited May 17 at 12:05
Frederik Struck-Schøning
9,69774151
9,69774151
answered Jun 15 '17 at 11:40
Baatar
20619
20619
add a comment |
add a comment |
up vote
2
down vote
I am using Angular 4 with the 4.3 httpClient object. I modified an answer I found in Js' Technical Blog which creates a link object, uses it to do the download, then destroys it.
Client:
doDownload(id: number, contentType: string) {
return this.http
.get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}
downloadFile(id: number, contentType: string, filename:string) {
return this.doDownload(id, contentType).subscribe(
res => {
var url = window.URL.createObjectURL(res);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove(); // remove the element
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.')
});
}
The value of this.downloadUrl has been set previously to point to the api. I am using this to download attachments, so I know the id, contentType and filename:
I am using an MVC api to return the file:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public FileContentResult GetAttachment(Int32 attachmentID)
{
Attachment AT = filerep.GetAttachment(attachmentID);
if (AT != null)
{
return new FileContentResult(AT.FileBytes, AT.ContentType);
}
else
{
return null;
}
}
The attachment class looks like this:
public class Attachment
{
public Int32 AttachmentID { get; set; }
public string FileName { get; set; }
public byte FileBytes { get; set; }
public string ContentType { get; set; }
}
The filerep repository returns the file from the database.
Hope this helps someone :)
add a comment |
up vote
2
down vote
I am using Angular 4 with the 4.3 httpClient object. I modified an answer I found in Js' Technical Blog which creates a link object, uses it to do the download, then destroys it.
Client:
doDownload(id: number, contentType: string) {
return this.http
.get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}
downloadFile(id: number, contentType: string, filename:string) {
return this.doDownload(id, contentType).subscribe(
res => {
var url = window.URL.createObjectURL(res);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove(); // remove the element
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.')
});
}
The value of this.downloadUrl has been set previously to point to the api. I am using this to download attachments, so I know the id, contentType and filename:
I am using an MVC api to return the file:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public FileContentResult GetAttachment(Int32 attachmentID)
{
Attachment AT = filerep.GetAttachment(attachmentID);
if (AT != null)
{
return new FileContentResult(AT.FileBytes, AT.ContentType);
}
else
{
return null;
}
}
The attachment class looks like this:
public class Attachment
{
public Int32 AttachmentID { get; set; }
public string FileName { get; set; }
public byte FileBytes { get; set; }
public string ContentType { get; set; }
}
The filerep repository returns the file from the database.
Hope this helps someone :)
add a comment |
up vote
2
down vote
up vote
2
down vote
I am using Angular 4 with the 4.3 httpClient object. I modified an answer I found in Js' Technical Blog which creates a link object, uses it to do the download, then destroys it.
Client:
doDownload(id: number, contentType: string) {
return this.http
.get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}
downloadFile(id: number, contentType: string, filename:string) {
return this.doDownload(id, contentType).subscribe(
res => {
var url = window.URL.createObjectURL(res);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove(); // remove the element
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.')
});
}
The value of this.downloadUrl has been set previously to point to the api. I am using this to download attachments, so I know the id, contentType and filename:
I am using an MVC api to return the file:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public FileContentResult GetAttachment(Int32 attachmentID)
{
Attachment AT = filerep.GetAttachment(attachmentID);
if (AT != null)
{
return new FileContentResult(AT.FileBytes, AT.ContentType);
}
else
{
return null;
}
}
The attachment class looks like this:
public class Attachment
{
public Int32 AttachmentID { get; set; }
public string FileName { get; set; }
public byte FileBytes { get; set; }
public string ContentType { get; set; }
}
The filerep repository returns the file from the database.
Hope this helps someone :)
I am using Angular 4 with the 4.3 httpClient object. I modified an answer I found in Js' Technical Blog which creates a link object, uses it to do the download, then destroys it.
Client:
doDownload(id: number, contentType: string) {
return this.http
.get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}
downloadFile(id: number, contentType: string, filename:string) {
return this.doDownload(id, contentType).subscribe(
res => {
var url = window.URL.createObjectURL(res);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove(); // remove the element
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.')
});
}
The value of this.downloadUrl has been set previously to point to the api. I am using this to download attachments, so I know the id, contentType and filename:
I am using an MVC api to return the file:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public FileContentResult GetAttachment(Int32 attachmentID)
{
Attachment AT = filerep.GetAttachment(attachmentID);
if (AT != null)
{
return new FileContentResult(AT.FileBytes, AT.ContentType);
}
else
{
return null;
}
}
The attachment class looks like this:
public class Attachment
{
public Int32 AttachmentID { get; set; }
public string FileName { get; set; }
public byte FileBytes { get; set; }
public string ContentType { get; set; }
}
The filerep repository returns the file from the database.
Hope this helps someone :)
edited May 18 at 7:17
Frederik Struck-Schøning
9,69774151
9,69774151
answered May 1 at 1:31
davaus
455410
455410
add a comment |
add a comment |
up vote
2
down vote
Update to Hector's answer using file-saver and HttpClient for step 2:
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
add a comment |
up vote
2
down vote
Update to Hector's answer using file-saver and HttpClient for step 2:
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
add a comment |
up vote
2
down vote
up vote
2
down vote
Update to Hector's answer using file-saver and HttpClient for step 2:
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
Update to Hector's answer using file-saver and HttpClient for step 2:
public downloadFile(file: File): Observable<Blob> {
return this.http.get(file.fullPath, {responseType: 'blob'})
}
answered Aug 23 at 20:50
dmcgrandle
1,134415
1,134415
add a comment |
add a comment |
up vote
2
down vote
Here's something I did in my case -
// 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"));
}
The solution is referenced from - here
add a comment |
up vote
2
down vote
Here's something I did in my case -
// 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"));
}
The solution is referenced from - here
add a comment |
up vote
2
down vote
up vote
2
down vote
Here's something I did in my case -
// 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"));
}
The solution is referenced from - here
Here's something I did in my case -
// 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"));
}
The solution is referenced from - here
answered Oct 1 at 10:07
Tushar Walzade
1,01021029
1,01021029
add a comment |
add a comment |
up vote
1
down vote
I got a solution for downloading from angular 2 without getting corrupt,
using spring mvc and angular 2
1st- my return type is :-ResponseEntity from java end. Here I am sending byte array has return type from the controller.
2nd- to include the filesaver in your workspace-in the index page as:
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
3rd- at component ts write this code:
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');
});
This will give you xls file format. If you want other formats change the mediatype and file name with right extension.
add a comment |
up vote
1
down vote
I got a solution for downloading from angular 2 without getting corrupt,
using spring mvc and angular 2
1st- my return type is :-ResponseEntity from java end. Here I am sending byte array has return type from the controller.
2nd- to include the filesaver in your workspace-in the index page as:
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
3rd- at component ts write this code:
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');
});
This will give you xls file format. If you want other formats change the mediatype and file name with right extension.
add a comment |
up vote
1
down vote
up vote
1
down vote
I got a solution for downloading from angular 2 without getting corrupt,
using spring mvc and angular 2
1st- my return type is :-ResponseEntity from java end. Here I am sending byte array has return type from the controller.
2nd- to include the filesaver in your workspace-in the index page as:
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
3rd- at component ts write this code:
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');
});
This will give you xls file format. If you want other formats change the mediatype and file name with right extension.
I got a solution for downloading from angular 2 without getting corrupt,
using spring mvc and angular 2
1st- my return type is :-ResponseEntity from java end. Here I am sending byte array has return type from the controller.
2nd- to include the filesaver in your workspace-in the index page as:
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
3rd- at component ts write this code:
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');
});
This will give you xls file format. If you want other formats change the mediatype and file name with right extension.
edited Dec 3 at 12:26
Mel
3,68592330
3,68592330
answered Jul 16 '17 at 12:33
user2025069
113
113
add a comment |
add a comment |
up vote
0
down vote
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();
});
add a comment |
up vote
0
down vote
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();
});
add a comment |
up vote
0
down vote
up vote
0
down vote
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();
});
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();
});
answered Aug 19 at 17:20
user2025069
113
113
add a comment |
add a comment |
up vote
0
down vote
It will be better if you try to call the new method inside you subscribe
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => onsole.log(error),
() => console.log('Complete')
);
Inside downloadFile(data)
function we need to make block, link, href and file name
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);
}
}
add a comment |
up vote
0
down vote
It will be better if you try to call the new method inside you subscribe
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => onsole.log(error),
() => console.log('Complete')
);
Inside downloadFile(data)
function we need to make block, link, href and file name
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);
}
}
add a comment |
up vote
0
down vote
up vote
0
down vote
It will be better if you try to call the new method inside you subscribe
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => onsole.log(error),
() => console.log('Complete')
);
Inside downloadFile(data)
function we need to make block, link, href and file name
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);
}
}
It will be better if you try to call the new method inside you subscribe
this._reportService.getReport()
.subscribe((data: any) => {
this.downloadFile(data);
},
(error: any) => onsole.log(error),
() => console.log('Complete')
);
Inside downloadFile(data)
function we need to make block, link, href and file name
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);
}
}
answered Aug 20 at 11:07
Volodymyr Khmil
19314
19314
add a comment |
add a comment |
up vote
0
down vote
Simply put the url
as href
as below .
<a href="my_url">Download File</a>
add a comment |
up vote
0
down vote
Simply put the url
as href
as below .
<a href="my_url">Download File</a>
add a comment |
up vote
0
down vote
up vote
0
down vote
Simply put the url
as href
as below .
<a href="my_url">Download File</a>
Simply put the url
as href
as below .
<a href="my_url">Download File</a>
answered Dec 7 at 11:00
Harunur Rashid
1,183510
1,183510
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f35138424%2fhow-do-i-download-a-file-with-angular2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown