Search code examples
javascriptreactjspdfreactjs-flux

Dowload PDF as a stream of bytes


I have web API that provides stores files as a stream of bytes. The response is already fetched and saved in the state but now I want to download the file from my react application onClick of a button. I am doing it as follow:

downloadContract( binaryData ) {
        const file = new Blob([binaryData], { type: 'application/pdf' });
        const fileURL = URL.createObjectURL(file);
        window.open(fileURL);
      }

The stream is being fetched correctly after debugging but downloading the file produces an error: Error loading PDF document.

Update:

New endpoint calling using this source:

  callLoadContract: {
    remote( state, id, contractId ) {
      const url = `${base}/vendor/${id}/${contractId }`;
      return $http.instance.api.get( url, id, contractId);
    },
    success: Actions.contractLoaded,
    error: Actions.fail
  }

Handling the response:

  loadContract({id, contractId}) {
    this.getInstance().callLoadContract( id, contractId );
  }

  contractLoaded( response ) {
    if (response && response.data) {
      console.log(response);
      const file = new Blob([response.data], { type: 'application/pdf' });
      const fileURL = URL.createObjectURL(file);
      window.open(fileURL);
    }
  }

Same error.


Solution

  • Maybe your problem is nothing related to the way to process the PDF in the client side as your code works pretty well:

    import React from 'react';
    
    export default class App extends React.Component {
        constructor(props, context) {
            super(props, context);
        }
    
        downloadContract() {
            var oReq = new XMLHttpRequest();
    
            var URLToPDF = "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf";
    
            oReq.open("GET", URLToPDF, true);
    
            oReq.responseType = "blob";
    
            oReq.onload = function() {
                // Once the file is downloaded, open a new window with the PDF
                // Remember to allow the POP-UPS in your browser
                const file = new Blob([oReq.response], { type: 'application/pdf' });
    
                const fileURL = URL.createObjectURL(file);
    
                window.open(fileURL, "_blank");
            };
    
            oReq.send();
        }
    
        render() {
            return (
                <div>
                    <input type="button" onClick={this.downloadContract} value="Download PDF File"/>
                </div>
            );
        }
    }
    

    As expected, the PDF will be downloaded and shown in a new Window of the browser when the user clicks on Download.

    However, the easiest approach is the mentioned by @drinchev, just server it in a URL and that's it.