Search code examples
djangoangularpdfdjango-rest-frameworkhttpresponse

Passing a pdf from Django backend to Angular frontend


I haven't been able to make any of the solutions to similar problems work for my case. I would like to load a pdf from filesystem with django and return it via an API call to Angular so that it can be displayed. My Django code is pretty much:

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

while on the Angular side I have a service that does this:

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))
    }
}

and a component that tries to open the pdf like this:

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);    
            }            
        }
    }
}

but nothing happens. I have also tried using different responses and passthrough renderers on the django side, and Observable<Response> and .then() callbacks like

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

on the Angular side. Sometimes I have managed to get the new window/tab to open but no pdf could be displayed.


Solution

  • I finally figured it out. In the python part, the read() can be removed with no problem. The issue was with the service response type and mapping of the response:

    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))
    }