[英]Axios keeps downloading a corrupted PDF
當我使用 axios 將 PDF 文件下載到客戶端時,它總是以損壞告終。 我有一個 MERN 堆棧網絡應用程序,它允許用戶單擊按鈕下載 PDF 文件。 單擊按鈕會向 Node.js Web 服務器發送 axios GET 請求。 我正在使用 express.js 來處理路由和請求。 快速路由將使用 Google API 將 Google Doc 作為 PDF 下載到 Node.js 服務器,然后我希望 Node.js 將該 PDF 發送到客戶端的瀏覽器。 一切正常,除了下載總是在客戶端損壞。 (pdf 下載並完美打開到 Node.js)
這是當用戶單擊按鈕時發送到 Node.js 的 Axios get 請求。 (我使用 react-redux 作為調度函數)。 我曾嘗試將 responseType 設置為“blob”,但不起作用。
export const downloadDocument = (googleDocId) => (dispatch) => {
dispatch({
type: DOCUMENT_DOWNLOADING
})
axios.get('/api/documents/download?googleDocId=' + googleDocId, {
responseType: 'arraybuffer'
})
.then(res => {
dispatch({
type: DOCUMENT_DOWNLOADED,
payload: res.data
})
const url = window.URL.createObjectURL(new Blob([res.data]), {
type: 'application/pdf'
})
const link = document.createElement('a')
link.href = url;
link.setAttribute('download', 'LOR.pdf')
document.body.appendChild(link)
link.click()
})
.catch(err => {
dispatch(returnErrors(err.response.data, err.response.status))
dispatch({
type: DOCUMENT_DOWNLOAD_FAIL
})
})
}
這是處理下載請求的后端 express.js 代碼:
erouter.get('/download', async (req, res) => {
const googleDocId = req.query.googleDocId
if (!googleDocId) {
return res.status(400).json({
msg: "googleDocId not specified"
})
}
//Use the Google API to download a PDF from Google Drive
const { google } = require("googleapis")
const fs = require('fs')
const auth = new google.auth.GoogleAuth({
keyFile: "credentials.json",
scopes: ["https://www.googleapis.com/auth/drive"]
})
//Create client instance for auth
const client = await auth.getClient()
// Instance of Google Drive API
const gDrive = google.drive({
version: "v3",
auth: client
})
//Download file as PDF from google Drive to node.js server
await gDrive.files.export({
fileId: googleDocId,
mimeType: 'application/pdf'
}, {
responseType: 'stream'
})
.then(response => {
return new Promise((resolve, reject) => {
const filePath = path.join(__dirname, "../../tmp")
console.log(`writing to ${filePath}`);
const dest = fs.createWriteStream(filePath);
let progress = 0
response.data
.on('end', () => {
console.log('Done downloading file.')
resolve(filePath)
})
.on('error', err => {
console.error('Error downloading file.')
reject(err)
})
.on('data', d => {
progress += d.length;
if (process.stdout.isTTY) {
process.stdout.clearLine()
process.stdout.cursorTo(0)
process.stdout.write(`Downloaded ${progress} bytes`)
}
})
.pipe(dest)
})
})
.catch(err => console.log(err))
//Download file to client browser
const options = {
root: path.join(__dirname, "../../tmp"),
headers: {
'Content-Type' : 'application/pdf'
}
}
var filename = "LOR.pdf"
res.sendFile(filename, options)
//res.download('./tmp/LOR.pdf')
})
可能出什么問題了? 在使用 responseType: 'arraybuffer' 之后的某個時候,按照其他在線 axios 線程的推薦,下載確實有效並下載了一次有效的 PDF,但是效果不一致並且幾乎總是導致客戶端瀏覽器上的 PDF 損壞。 有人請幫助我快瘋了。 我曾嘗試使用 download.js npm 包,但這並沒有給我想要的結果。 我也嘗試過這些線程的建議: https : //gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743 https://github.com/axios/axios/issues/448 <-第二個鏈接中的這個解決方案工作一次,然后后來不斷導致損壞的PDF下載
我讓它完全按照我的意圖工作! 謝謝菲爾的指導。 Google API 流式傳輸 PDF,將管道連接到 express res 對象,並將 PDF 直接流式傳輸到 res,我可以將其重建為另一側的 blob。 它現在可以工作,根本不需要將 PDF 寫入 node.js 服務器!
//Stream file as PDF from google Drive and pipe it to express res
gDrive.files.export({fileId: googleDocId, mimeType: 'application/pdf'}, {responseType: 'stream'})
.then(response => {
return new Promise((resolve, reject) => {
console.log('Beginning download stream')
let progress = 0
response.data
.on('end', () => {
console.log('Done downloading file.')
resolve()
})
.on('error', err => {
console.error('Error downloading file.')
reject(err)
})
.on('data', d => {
progress += d.length;
if (process.stdout.isTTY) {
process.stdout.clearLine()
process.stdout.cursorTo(0)
process.stdout.write(`Downloaded ${progress} bytes`)
}
})
.pipe(res) //Pipe data to the express res object
})
})
.catch(err => console.log(err))
試試這個,它應該工作
// Your code
const url = window.URL.createObjectURL(new File([new Blob([res.data])], "LOR.pdf", {type: 'application/pdf'}))
// Your code
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.