Чтение и отправка pdf с узла на клиент - пустые страницы - PullRequest
0 голосов
/ 09 мая 2018

В настоящее время я читаю PDF через бэкэнд узла, отправляю его через слой шлюза API и обратно клиенту - однако, когда ответ попадает в клиент, файл PDF загружается с правильным количеством страниц, но полностью пустым , Я попытался установить кодировку несколькими способами, но безуспешно. При установке двоичной кодировки и выполнении различий между загруженным PDF и оригинальным PDF видимых различий не наблюдается, даже если размеры файлов различаются.

Бэкэнд узла: `

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

`

Шлюз API просто отправляет запрос бэкэнду узла и устанавливает тип контента перед отправкой: `

res.setHeader('Content-Type', 'application/pdf')

`

Frontend: `

function retrievePDF () {
  return fetch('backendurlhere', {
    method: 'GET',
    headers: { 'Content-Type': 'application/pdf' },
    credentials: 'include'
  })
    .then(response => {
      return response.text()
    })
    .catch(err => {
      console.log('ERR', err)
  })

`

вызывается retrievePDF, а затем через компонент React выполняется следующее: `

  generatePDF () {
    this.props.retrievePDF()
      .then(pdfString => {
        const blob = new Blob([pdfString], { type: 'application/pdf' })
        const objectUrl = window.URL.createObjectURL(blob)
        window.open(objectUrl)
      })
  }

`

Строковое представление ответа выглядит примерно так (просто пример): `

%PDF-1.4
1 0 obj
<<
/Title (þÿ)
/Creator (þÿ)
/Producer (þÿQt 5.5.1)
/CreationDate (D:20171003224921)
>>
endobj
2 0 obj
<<
/Type /Catalog
/Pages 3 0 R
>>
endobj
4 0 obj
<<
/Type /ExtGState
/SA true
/SM 0.02
/ca 1.0
/CA 1.0
/AIS false
/SMask /None>>
endobj
5 0 obj
[/Pattern /DeviceRGB]
endobj
6 0 obj
<<
/Type /Page
/Parent 3 0 R
/Contents 8 0 R
/Resources 10 0 R
/Annots 11 0 R
/MediaBox [0 0 142 256]
>>
endobj
10 0 obj
<<
/ColorSpace <<
/PCSp 5 0 R
/CSp /DeviceRGB
/CSpg /DeviceGray
>>
/ExtGState <<
/GSa 4 0 R
>>
/Pattern <<
>>
/Font <<
/F7 7 0 R
>>
/XObject <<
>>
>>
endobj
11 0 obj
[ ]
endobj
8 0 obj
<<
/Length 9 0 R
/Filter /FlateDecode
>>
stream
xåW]kÂ0}ϯ¸ÏÕ$mÆ`V6{{ºÊûûKÓ´vS¥N_f°WsÒ{ÏýÈMÛ»<ÑëzÙä¦Af&»q^©4MlE+6fcw-äUwp?ÖÓ%ëºX93Éî/tã¾·næ5Å¢trîeaiÎx-ù7vFËCí5nl¢¸Myláïmå·Ïgö²G±T  ¹ïÒZk¢ð£¹¼)<äµµ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 ¢à>ëRÄ]ZNæÚÂú¿·PWÒU4¢ØR]Ê®Kj±6\\ÐNØFG¬Ô;ÝRLüݱP[>·~'½%ä8M8丸0ýiiÕ}ت³S$=N*s'>¹³§VùGfûÉU`ËÁ¥wú®FéC^½"òºBcö
Ùå@endstream
endobj

`

HTTP-ответ выглядит следующим образом: `

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

`

Я также попробовал другие методы чтения файла, такие как readFileSync, и создание фрагментов с помощью fStream.on ('data') и отправку обратно в виде буфера. Кажется, ничего не работает.

Примечание: я использую Restify (не экспресс)

Edit: Запуск файла через валидатор показывает следующее: `

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.

`

1 Ответ

0 голосов
/ 10 мая 2018

Для тех, у кого возникли проблемы, я обнаружил, что в слое шлюза запрос был обернут вокруг служебной функции, которая выполняла чтение текста ответа, т.е.

return response.text()

Я удалил это и вместо этого передал ответ от бэкэнда:

fetch('backendurl') .then(({ body }) => { body.pipe(res) })

Надеюсь, это поможет любому, кто использует шаблон шлюза с похожими проблемами

...