Angular 2 downloading a file: corrupt result
Asked Answered
S

2

7

I am attempting to download a file using Angular 2/TypeScript and Web API. The problem I am having is that when downloading the text file, the file is file but when attempting to download an PDF file, for example, it is corrupted. The contents of the downloaded file is garbled nonsense.

The TypeScript I am using is as follows:

downloadFile(fileId: string): Observable<File> {
    this.applicationsUrl = `${APIConfig.BaseUrl}/documents/download/${fileId}/`;

    let headers = new Headers({ 'Content-Type': 'application/json', 'MyApp-Application' : 'AppName' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.applicationsUrl, '', options)
        .map(this.extractContent)
        .catch(this.handleError);
}

private extractContent(res: any) {
    let blob: Blob = new Blob([res._body], { type: 'application/pdf'});
    window['saveAs'](blob, 'test.pdf');
}

The window['saveAs'] is just a workaround to access the JavaScript FileSaver.js functions.

Additionally I have set res:Response to res:any so I can access the private _body property under JavaScript without a compile failure in TypeScript.

Any help would be greatly appreciated.

Sitnik answered 5/8, 2016 at 16:25 Comment(0)
B
12

As of Angular RC5 following code should work for you:

downloadFile(fileId: string): Observable<File> {
this.applicationsUrl = `${APIConfig.BaseUrl}/documents/download/${fileId}/`;

let headers = new Headers({ 'Content-Type': 'application/json', 'MyApp-Application' : 'AppName', 'Accept': 'application/pdf' });
let options = new RequestOptions({ headers: headers, responseType: ResponseContentType.Blob });

return this.http.post(this.applicationsUrl, '', options)
    .map(this.extractContent)
    .catch(this.handleError);
}

private extractContent(res: Response) {
    let blob: Blob = res.blob();
    window['saveAs'](blob, 'test.pdf');
}

I had a similar Problem and setting the Accept-Header to application/pdf, responseType to Blob and accessing the blob through the corresponding Method on the Response resolved this for me :) (I'm using FileSaver, too)

Bugle answered 13/9, 2016 at 13:51 Comment(1)
How are you using FileSaver? Can you give an example of using it in Typescript?Chemosmosis
T
0

We were having a similar issue and had to configure a messageConverter on the spring side. The code snippet below is from Spring config file :-

    @Override
     public void configureMessageConverters(List<HttpMessageConverter<?>> 
         converters) {
    //Here we add our custom-configured HttpMessageConverter
   /* Message converter for supporting Hibernate lazy objects */
    converters.add(jacksonMessageConverter());
    converters.add(byteArrayHttpMessageConverter());
    super.configureMessageConverters(converters);
}

    public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
    return arrayHttpMessageConverter;
} 

private List<MediaType> getSupportedMediaTypes() {
    List<MediaType> list = new ArrayList<MediaType>();
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    list.add(MediaType.parseMediaType("application/pdf"));
    return list;
}

More details on configuring message converters can be found here:- http://www.baeldung.com/spring-httpmessageconverter-rest

You still need to add the "Accept" header in the request as answered by Chris. This will help map the response to an appropriate message converter configured on the spring side.

Telly answered 20/4, 2018 at 21:18 Comment(1)
This might be too late, but may benefit someone else!Telly

© 2022 - 2024 — McMap. All rights reserved.