我目前正在通过节点后端读取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)
})
`
调用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')构建块并作为Buffer发送回来。似乎没什么用。
注意:我正在使用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.
`
答案 0 :(得分:1)
对于任何有问题的人,我发现在我的网关层中,请求被包含在一个实用函数中,该函数执行对响应的文本读取,即
return response.text()
我删除了这个,而是通过后端管道响应:
fetch('backendurl') .then(({ body }) => { body.pipe(res) })
希望这可以帮助任何使用网关模式的人遇到类似的问题