将 pdf 从 Django 后端传递到 Angular 前端

Passing a pdf from Django backend to Angular frontend

我无法使类似问题的任何解决方案适用于我的案例。 我想使用 django 从文件系统加载一个 pdf,并通过 API 调用 Angular 来 return 它,以便可以显示它。我的 Django 代码差不多是:

class LoadPdfViewSet(views.APIView):
    def get(self, request):
        # some code here here
        response = FileResponse(open(path_to_pdf, 'rb').read())
        response.headers = {   
            'Content-Type': 'application/pdf',
            'Content-Disposition': 'attachment;filename="report.pdf"',
        }
        response.as_attachment = True
        return response

而在 Angular 方面,我有一项服务可以做到这一点:

export class LoadPdfService {
    constructor(
        private http: HttpClient
    ) {}

    getPdf(): Observable<Blob> {
        const params = new HttpParams({
            fromObject: { 
                responsetype: 'arraybuffer' 
                // other stuff here
            }
        })
        return self.http.get<Blob>(loadpdf_api_url, {params}).pipe(catchError(self.myErrorHandler))
    }
}

和一个尝试像这样打开 pdf 的组件:

export class MyComponent {
    constructor(
        public loadPdfService: LoadPdfService
    ) {}

    download_pdf() {
        let call = self.loadPdfService.getPdf();
        call.subscribe( (response:Blob) => {
            if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE
                window.navigator.msSaveOrOpenBlob(blob, "report.pdf");
            } else {
                let pdfUrl = URL.createObjectURL(blob)
                window.open(pdfUrl, '_blank')
                URL.revokeObjectURL(pdfUrl);    
            }            
        }
    }
}

但是没有任何反应。我还尝试在 django 端使用不同的响应和直通渲染器,以及 Observable<Response>.then() 回调,如

response.arrayBuffer().then(buffer => new Blob([buffer], {type: 'application/pdf'}))

在 Angular 一侧。有时我设法让新 window/tab 打开但无法显示 pdf。

我终于明白了。在 python 部分, read() 可以毫无问题地删除。问题在于服务响应类型和响应映射:

getPdf(): Observable<Blob> {
    const options = {
        params: new HttpParams({
            fromObject: {
                // my own parameters here
            }
        }),
        responseType: 'blob' as 'json'
    };

    return this.http.get(this.url, options).pipe(
        map(response => response as Blob),
        catchError(this.myErrorHandler))
}