Angular で PDF ファイルをダウンロードする方法
ユース ケース: バックエンドから受信した blob 応答または base64 でエンコードされた文字列を解析し、その場で PDF ファイルをダウンロードします.
バックエンド サービスが BLOB データを応答として送信する
またはbase64でエンコードされた文字列
ここでの最初のステップは、応答を処理して解析することです.応答が base64 文字列の場合、ファイルのダウンロードは BLOB データのみで可能であるため、まずそれを BLOB オブジェクトに変換する必要があります.
BLOB オブジェクトの準備ができたら、ファイルをダウンロードするか、新しいタブでファイルを開き、ユーザーがそのファイルをダウンロードするかどうかを決定できるようにします.
ファイルを直接ダウンロードするシナリオを見てみましょう.
アンカー タグを作成し、オブジェクト URL を に割り当てます ダウンロードを開始します
ファイルをダウンロードするつもりがなく、代わりにファイルを新しいタブで開き、ユーザーがそれをダウンロードするか、単に読んでタブを閉じるかを決定できるようにする場合は、以下の手順に従います.
ファイルをダウンロードするか、コンテンツを読むだけかをユーザーがより柔軟に判断できるため、個人的にはこのアプローチが気に入っています.このアプローチの唯一の欠点は、ダウンロードしたファイルにカスタム ファイル名を割り当てることができないことです.
Safari ブラウザーは、セキュリティ上の理由から、これまでに実装した (BLOB URL を使用した) アプローチをサポートしていません. Safari ブラウザーでのダウンロードを可能にするために、サードパーティのライブラリー file-saver-es を利用します.
Android v5 以下の場合、Web ビューが BLOB オブジェクトを認識しないためにダウンロードが失敗するシナリオがあります. FileReader API を使用してその BLOB オブジェクトを base64 文字列に変換してから、ダウンロードを開始する必要があります.
バックエンド サービスが BLOB データを応答として送信する
%PDF-1.5
%âãÏÓ
1 0 obj
/Type/Page/Parent 8 0 R /MediaBox[ 0 0 612 792]/Contents 9 0 R /Resources/XObject/img49352 7 0 R /img49350 6 0 R /img49348 5 0 R /img49347 3 0 R /Font/F2 2 0 R /F4 4 0 R
endobj.................
またはbase64でエンコードされた文字列
data:application/pdf;base64,JVBERi0xLjUKJeLjz9MKMSAwI.....
ここでの最初のステップは、応答を処理して解析することです.応答が base64 文字列の場合、ファイルのダウンロードは BLOB データのみで可能であるため、まずそれを BLOB オブジェクトに変換する必要があります.
private processFileResponse(fileResponseData: any, fileName: string, render: string): void {
if (render === 'base64') {
this.base64Response = fileResponseData;
const binaryString = window.atob(fileResponseData);
const bytes = new Uint8Array(binaryString.length);
const binaryToBlob = bytes.map((byte, i) => binaryString.charCodeAt(i));
const blob = new Blob([binaryToBlob], { type: 'application/pdf' });
this.downloadFile(blob, fileName, render);
} else {
const blob = new Blob([fileResponseData], { type: 'application/pdf' });
this.downloadFile(blob, fileName, render);
}
}
BLOB オブジェクトの準備ができたら、ファイルをダウンロードするか、新しいタブでファイルを開き、ユーザーがそのファイルをダウンロードするかどうかを決定できるようにします.
ファイルを直接ダウンロードするシナリオを見てみましょう.
createObjectURL()
を使用してオブジェクト URL を準備するhref
属性 private downloadFile(blob: any, fileName: string): void {
// IE Browser
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
// Other Browsers
const url = (window.URL || window.webkitURL).createObjectURL(blob);
const link = this.renderer.createElement('a');
this.renderer.setAttribute(link, 'download', fileName);
this.renderer.setAttribute(link, 'href', url);
this.renderer.setAttribute(link, 'target', '_blank');
this.renderer.appendChild(this.elementRef.nativeElement, link);
link.click();
this.renderer.removeChild(this.elementRef.nativeElement, link);
setTimeout(() => {
window.URL.revokeObjectURL(url);
}, 1000);
}
Once the process is completed, make sure you have revoked the object URL else that will pile up on the browser's memory
ファイルをダウンロードするつもりがなく、代わりにファイルを新しいタブで開き、ユーザーがそれをダウンロードするか、単に読んでタブを閉じるかを決定できるようにする場合は、以下の手順に従います.
private downloadFile(blob: any, fileName: string): void {
// IE Browser
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
// Other Browsers
const url = (window.URL || window.webkitURL).createObjectURL(blob);
window.open(url, '_blank');
// rewoke URL after 15 minutes
setTimeout(() => {
window.URL.revokeObjectURL(url);
}, 15 * 60 * 1000);
}
ファイルをダウンロードするか、コンテンツを読むだけかをユーザーがより柔軟に判断できるため、個人的にはこのアプローチが気に入っています.このアプローチの唯一の欠点は、ダウンロードしたファイルにカスタム ファイル名を割り当てることができないことです.
IOS (apple) デバイスでのエッジ ケースの処理
Safari ブラウザーは、セキュリティ上の理由から、これまでに実装した (BLOB URL を使用した) アプローチをサポートしていません. Safari ブラウザーでのダウンロードを可能にするために、サードパーティのライブラリー file-saver-es を利用します.
import { saveAs } from 'file-saver-es';
...
private downloadFile(blob: any, fileName: string): void {
...
if (this.useFileSaverAPI()) {
saveAs(blob, fileName);
} else {
// rest of devices and browsers
window.open(url, '_blank');
}
}
private useFileSaverAPI(): boolean {
return (/(iPad|iPhone|iPod)/g.test(navigator.platform || navigator.userAgent) || ((navigator.platform || navigator.userAgent) === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream;
}
古い Android Web ビュー (v5 以下) でのエッジ ケースの処理
Android v5 以下の場合、Web ビューが BLOB オブジェクトを認識しないためにダウンロードが失敗するシナリオがあります. FileReader API を使用してその BLOB オブジェクトを base64 文字列に変換してから、ダウンロードを開始する必要があります.
if (this.isAndroid()) {
if (this.base64Response) {
window.open(this.base64Response, '_blank');
} else {
const fileReader = new FileReader();
fileReader.readAsDataURL(blob);
fileReader.onloadend = () => {
window.open(fileReader.result as any, '_blank');
};
}
} else {
// rest of devices and browsers
window.open(url, '_blank');
}
private isAndroid(): boolean {
return (/(android)/i.test(navigator.platform || navigator.userAgent)
}
Reference
この問題について(Angular で PDF ファイルをダウンロードする方法), 我々は、より多くの情報をここで見つけました https://dev.to/aakashgoplani/how-to-download-pdf-files-in-angular-1bglテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol