Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

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.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author