How to download files in Angular
Downloading files in Angular requires fetching the file as a binary blob, creating an object URL, and triggering a click on a hidden anchor element to initiate the browser download.
As the creator of CoreUI with Angular development experience since 2014, I’ve implemented file downloads for PDF reports, CSV exports, and document management in enterprise Angular applications.
The key is setting responseType: 'blob' on the HttpClient request and extracting the filename from the Content-Disposition header when the server provides it.
This works for any file type — PDFs, ZIPs, Excel files, images — without requiring any third-party library.
Create a service that downloads files and triggers browser save dialog.
// download.service.ts
import { Injectable } from '@angular/core'
import { HttpClient, HttpResponse } from '@angular/common/http'
import { Observable } from 'rxjs'
@Injectable({ providedIn: 'root' })
export class DownloadService {
constructor(private http: HttpClient) {}
downloadFile(url: string, fallbackFilename = 'download'): void {
this.http.get(url, {
responseType: 'blob',
observe: 'response'
}).subscribe({
next: (response: HttpResponse<Blob>) => {
const blob = response.body!
const filename = this.getFilename(response, fallbackFilename)
this.saveBlob(blob, filename)
},
error: (err) => console.error('Download failed:', err)
})
}
private getFilename(response: HttpResponse<Blob>, fallback: string): string {
const disposition = response.headers.get('Content-Disposition')
if (disposition) {
const match = disposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
if (match?.[1]) {
return match[1].replace(/['"]/g, '')
}
}
return fallback
}
private saveBlob(blob: Blob, filename: string): void {
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = filename
anchor.click()
URL.revokeObjectURL(url)
}
}
responseType: 'blob' tells Angular to parse the response body as binary data. observe: 'response' gives access to the full HttpResponse including headers, which is needed to read Content-Disposition. URL.createObjectURL creates a temporary URL for the blob, and URL.revokeObjectURL releases memory after the click.
Using the Download Service in a Component
Trigger downloads from a button click.
// report.component.ts
import { Component } from '@angular/core'
import { DownloadService } from './download.service'
@Component({
selector: 'app-report',
standalone: true,
template: `
<button (click)="downloadPDF()">Download PDF Report</button>
<button (click)="downloadCSV()">Export as CSV</button>
`
})
export class ReportComponent {
constructor(private download: DownloadService) {}
downloadPDF(): void {
this.download.downloadFile('/api/reports/monthly.pdf', 'monthly-report.pdf')
}
downloadCSV(): void {
this.download.downloadFile('/api/reports/data.csv', 'report-data.csv')
}
}
The component calls the service with the API endpoint and a fallback filename. If the server sends a Content-Disposition: attachment; filename="report-2026-03.pdf" header, the browser uses that filename instead.
Downloading Already-Known URLs
For public, non-authenticated files, a simple anchor tag is sufficient.
@Component({
selector: 'app-asset',
standalone: true,
template: `
<a [href]="fileUrl" download="asset.pdf" target="_blank">
Download Asset
</a>
`
})
export class AssetComponent {
readonly fileUrl = '/assets/docs/guide.pdf'
}
The download attribute on an <a> tag triggers a download instead of navigation. This works only for same-origin URLs or when the server sets the appropriate CORS and Content-Disposition headers.
Best Practice Note
This is the same download pattern used in CoreUI Angular templates for reporting and document management pages. For large files, add a loading state and use HttpRequest with reportProgress: true to show a download progress indicator. Always set the correct Content-Type and Content-Disposition headers on your server — browsers use these to determine how to handle the downloaded file. See how to export data to CSV in Angular for generating CSV files directly in the browser without a server round trip.



