从节点读取和发送 pdf 到客户端 - 空白页



我目前正在通过节点后端读取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')

'

前端: `

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

'

检索PDF被调用,然后通过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(非快递(

编辑: 通过验证程序运行文件将显示以下内容: `

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.

'

对于任何有问题的人,我发现在我的网关层中,请求被包裹在一个实用程序函数周围,该实用程序函数对响应执行文本读取,即

return response.text()

我删除了它,而是从后端通过管道传输响应:

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

希望这有助于任何使用网关模式遇到类似问题的人

最新更新