title: Reading and sending a pdf from node to client - blank pages
body: <p>I'm currently reading a PDF via a node backend, sending it through an API gateway layer and back to the client - when the response hits the client however, the pdf is downloaded with the correct number of pages but is completely blank. I've tried setting the encoding in a number of ways but with no luck. When setting the encoding to binary and running a diff of the downloaded PDF vs the original PDF, there are no visible differences even though the filesizes differ.</p>
  
  <p>Node backend:
  `</p>
  
  <pre><code>export async function generatePDF (req, res, next) {
    try {
      const fStream = fs.createReadStream(path.join(__dirname, 'businesscard.pdf'), { encoding: 'binary' }) // have also tried without the binary encoding
      return fStream.pipe(res)
    } catch (err) {
      res.send(err)
    }
  }
  </code></pre>
  
  <p>`</p>
  
  <p>The API Gateway simply sends a request to the node backend and sets the content type before sending it on:
  `</p>
  
  <pre><code>res.setHeader('Content-Type', 'application/pdf')
  </code></pre>
  
  <p>`</p>
  
  <p>Frontend:
  `</p>
  
  <pre><code>function retrievePDF () {
    return fetch('backendurlhere', {
      method: 'GET',
      headers: { 'Content-Type': 'application/pdf' },
      credentials: 'include'
    })
      .then(response =&gt; {
        return response.text()
      })
      .catch(err =&gt; {
        console.log('ERR', err)
    })
  </code></pre>
  
  <p>`</p>
  
  <p>retrievePDF is called and then the following is performed via a React component:
  `</p>
  
  <pre><code>  generatePDF () {
      this.props.retrievePDF()
        .then(pdfString =&gt; {
          const blob = new Blob([pdfString], { type: 'application/pdf' })
          const objectUrl = window.URL.createObjectURL(blob)
          window.open(objectUrl)
        })
    }
  </code></pre>
  
  <p>`</p>
  
  <p>The string representation of the response looks a bit like this (simply a sample):
  `</p>
  
  <pre><code>%PDF-1.4
  1 0 obj
  &lt;&lt;
  /Title (þÿ)
  /Creator (þÿ)
  /Producer (þÿQt 5.5.1)
  /CreationDate (D:20171003224921)
  &gt;&gt;
  endobj
  2 0 obj
  &lt;&lt;
  /Type /Catalog
  /Pages 3 0 R
  &gt;&gt;
  endobj
  4 0 obj
  &lt;&lt;
  /Type /ExtGState
  /SA true
  /SM 0.02
  /ca 1.0
  /CA 1.0
  /AIS false
  /SMask /None&gt;&gt;
  endobj
  5 0 obj
  [/Pattern /DeviceRGB]
  endobj
  6 0 obj
  &lt;&lt;
  /Type /Page
  /Parent 3 0 R
  /Contents 8 0 R
  /Resources 10 0 R
  /Annots 11 0 R
  /MediaBox [0 0 142 256]
  &gt;&gt;
  endobj
  10 0 obj
  &lt;&lt;
  /ColorSpace &lt;&lt;
  /PCSp 5 0 R
  /CSp /DeviceRGB
  /CSpg /DeviceGray
  &gt;&gt;
  /ExtGState &lt;&lt;
  /GSa 4 0 R
  &gt;&gt;
  /Pattern &lt;&lt;
  &gt;&gt;
  /Font &lt;&lt;
  /F7 7 0 R
  &gt;&gt;
  /XObject &lt;&lt;
  &gt;&gt;
  &gt;&gt;
  endobj
  11 0 obj
  [ ]
  endobj
  8 0 obj
  &lt;&lt;
  /Length 9 0 R
  /Filter /FlateDecode
  &gt;&gt;
  stream
  xåW]kÂ0}Ï¯¸ÏÕ$mÆ`V6{{ºÊûûKÓ´vS¥N_f°WsÒ{ÏýÈMÛ»&lt;ÑëzÙä¦Af&amp;»q^©4MlE+6fcw-äUwp?ÖÓ%ëºX93Éî/tã¾·næ5Å¢trîeaiÎx-ù7vFËCí5nl¢¸Myláïmå·Ïgö²G±T  ¹ïÒZk¢ð£¹¼)&lt;äµµwm7ösÖ2¿P#¥ryëþèò]pÎÅ%åïÌDRqÿ)ôHTxpÄQOtjTI"ØBGd¤º
  ¢=¢£8Ú¶c¢téÑIþ¶c¡¶æ.ÇK»¾
  ä¥.Inþ)(ÚbX¹Mqs«b²5B¡vÚ ò·ÚNeçmÇ.![¨±87¿ÜÂõ[H ¢à&gt;ëRÄ]ZNæÚÂú¿·PWÒU4¢ØR]Ê®Kj±6\\ÐNØFG¬Ô;ÝRLüÝ±P[&gt;·~'½%ä8M8ä¸¸0ýiiÕ}Øª³S$=N*s'&gt;¹³§VùGfûÉU`ËÁ¥wú®FéC^½"òºBcö
  Ùå@endstream
  endobj
  </code></pre>
  
  <p>`</p>
  
  <p>The HTTP response looks as follows:
  `</p>
  
  <pre><code>access-control-allow-credentials: true
  access-control-allow-origin: http://frontend.dev.com
  access-control-expose-headers: api-version, content-length, content-md5, content-type, date, request-id, response-time
  Connection: keep-alive
  Content-Encoding: gzip
  Content-Type: application/octet-stream
  Date: Wed, 09 May 2018 09:37:22 GMT
  Server: nginx/1.13.3
  Transfer-Encoding: chunked
  vary: origin
  </code></pre>
  
  <p>`</p>
  
  <p>I've also tried other methods of reading the file, such as readFileSync, and constructing chunks via fStream.on('data') and sending back as a Buffer. Nothing seems to work.</p>
  
  <p>Note: I'm using Restify (not express)</p>
  
  <p>Edit:
  Running the file through a validator shows the following:
  `</p>
  
  <pre><code>File    teststring.pdf
  Compliance  pdf1.4
  Result  Document does not conform to PDF/A.
  Details 
  Validating file "teststring.pdf" for conformance level pdf1.4
  
  The 'xref' keyword was not found or the xref table is malformed.
  
  The file trailer dictionary is missing or invalid.
  
  The "Length" key of the stream object is wrong.
  
  Error in Flate stream: data error.
  
  The "Length" key of the stream object is wrong.
  
  Error in Flate stream: data error.
  
  The document does not conform to the requested standard.
  
  The file format (header, trailer, objects, xref, streams) is corrupted.
  
  The document does not conform to the PDF 1.4 standard.
  
  Done.
  </code></pre>
  
  <p>`</p>