如何通过Puppeteer.js下载XML文件?求解决方案
Puppeteer下载XML/文档文件崩溃问题排查与解决
问题背景
使用Puppeteer下载XML文件时程序反复崩溃,尝试下载DOCX文件也遇到类似报错,以下是两次尝试的代码及报错信息:
尝试1:点击DOCX文件链接
报错信息:buffer error message: Could not load body for this request. This might happen if the request is a preflight request.
报错代码片段(第26行):
let buffer; page.on("response", async response => { if(response.url().endsWith('.docx')){ try { //CAUSE OF ERROR buffer = await response.buffer() } catch (error) { console.error(`buffer error message: ${error.message}`) } } });
完整代码:
const puppeteer = require('puppeteer-extra') const downloadFile = async () => { //创建浏览器会话 const browser = await puppeteer.launch({ headless: true, userDataDir: "./BrowserData" }); //创建页面 const page = (await browser.pages())[0]; await page.setRequestInterception(true) //允许所有请求通过 page.on('request', async request => { request.continue(); }); //检测.docx类型响应并保存到缓冲区 let buffer; page.on("response", async response => { if(response.url().endsWith('.docx')){ try { //报错位置 buffer = await response.buffer() } catch (error) { console.error(`buffer error message: ${error.message}`) } } }); //在谷歌搜索.docx链接 try { await page.goto("https://www.google.com/search?q=type%3Adocx&sxsrf=ALiCzsYSc2CfabaHQHZdsQMgxFOFv2y0OQ%3A1664557191759&ei=hyA3Y93tLcLY5NoP0oO48A4&ved=0ahUKEwidzf3g_rz6AhVCLFkFHdIBDu4Q4dUDCA4&uact=5&oq=type%3Adocx&gs_lcp=Cgdnd3Mtd2l6EAM6CggAEEcQ1gQQsANKBAhBGABKBAhGGABQpAZYpAZg1AhoAXABeACAATuIATuSAQExmAEAoAEByAEIwAEB&sclient=gws-wiz"); } catch(e){ console.error("error message:", e) } //找到.docx链接的锚点标签 const link = await page.$("a[href='https://calibre-ebook.com/downloads/demos/demo.docx']"); //点击.docx文件链接 await page.evaluate((link) => { link.click(); }, link); }; downloadFile();
尝试2:直接跳转至DOCX文件链接
报错信息:Error: net::ERR_ABORTED at https://calibre-ebook.com/downloads/demos/demo.docx
报错代码片段(第32行):
//跳转到文件页面 try { //报错位置 await page.goto("https://calibre-ebook.com/downloads/demos/demo.docx"); } catch(e){ console.error("error message:", e) }
完整代码:
const puppeteer = require('puppeteer-extra') const downloadFile = async () => { //创建浏览器会话 const browser = await puppeteer.launch({ headless: true, userDataDir: "./BrowserData" }); //创建页面 const page = (await browser.pages())[0]; await page.setRequestInterception(true) //允许所有请求通过 page.on('request', async request => { request.continue(); }); //检测.docx类型响应并保存到文件 page.on("response", async response => { if(response.url().endsWith('.docx')){ try { const buffer = await response.buffer() } catch (error) { console.error(`buffer error message: ${error.message}`); } } }) //跳转到文件页面 try { //报错位置 await page.goto("https://calibre-ebook.com/downloads/demos/demo.docx"); } catch(e){ console.error("error message:", e) } }; downloadFile();
核心问题分析
尝试1报错原因:
- 点击文件链接时,浏览器可能触发OPTIONS预检请求,这类请求无响应体,调用
response.buffer()必然报错。 page.evaluate点击链接后页面跳转,导致响应被中断,无法完整获取文件内容。
- 点击文件链接时,浏览器可能触发OPTIONS预检请求,这类请求无响应体,调用
尝试2报错原因:
page.goto用于加载网页,而非处理二进制文件下载。浏览器触发下载流程时会中止goto请求,抛出ERR_ABORTED错误。
解决方法
方法1:禁用请求拦截,直接处理有效响应
无需启用page.setRequestInterception(true),直接监听response事件,过滤有效响应后保存:
const puppeteer = require('puppeteer-extra'); const fs = require('fs').promises; const downloadFile = async () => { const browser = await puppeteer.launch({ headless: true, userDataDir: "./BrowserData" }); const page = (await browser.pages())[0]; page.on("response", async response => { const url = response.url(); // 匹配XML或DOCX文件 if (url.endsWith('.xml') || url.endsWith('.docx')) { // 跳过预检请求,只处理成功响应 if (response.ok() && response.request().method() !== 'OPTIONS') { try { const buffer = await response.buffer(); const fileName = url.split('/').pop(); await fs.writeFile(`./${fileName}`, buffer); console.log(`文件${fileName}保存成功`); } catch (error) { console.error(`保存文件失败: ${error.message}`); } } } }); await page.goto("https://www.google.com/search?q=type%3Adocx&sxsrf=ALiCzsYSc2CfabaHQHZdsQMgxFOFv2y0OQ%3A1664557191759&ei=hyA3Y93tLcLY5NoP0oO48A4&ved=0ahUKEwidzf3g_rz6AhVCLFkFHdIBDu4Q4dUDCA4&uact=5&oq=type%3Adocx&gs_lcp=Cgdnd3Mtd2l6EAM6CggAEEcQ1gQQsANKBAhBGABKBAhGGABQpAZYpAZg1AhoAXABeACAATuIATuSAQExmAEAoAEByAEIwAEB&sclient=gws-wiz"); const link = await page.$("a[href='https://calibre-ebook.com/downloads/demos/demo.docx']"); if (link) { await link.click(); // 等待文件下载完成,根据实际情况调整时长 await page.waitForTimeout(3000); } await browser.close(); }; downloadFile();
方法2:提取URL后用HTTP库直接下载
对于已知文件URL,跳过Puppeteer的浏览器下载流程,用node-fetch直接下载:
const puppeteer = require('puppeteer-extra'); const fetch = require('node-fetch'); const fs = require('fs').promises; const downloadFile = async () => { const browser = await puppeteer.launch({ headless: true, userDataDir: "./BrowserData" }); const page = (await browser.pages())[0]; await page.goto("https://www.google.com/search?q=type%3Adocx&sxsrf=ALiCzsYSc2CfabaHQHZdsQMgxFOFv2y0OQ%3A1664557191759&ei=hyA3Y93tLcLY5NoP0oO48A4&ved=0ahUKEwidzf3g_rz6AhVCLFkFHdIBDu4Q4dUDCA4&uact=5&oq=type%3Adocx&gs_lcp=Cgdnd3Mtd2l6EAM6CggAEEcQ1gQQsANKBAhBGABKBAhGGABQpAZYpAZg1AhoAXABeACAATuIATuSAQExmAEAoAEByAEIwAEB&sclient=gws-wiz"); const link = await page.$("a[href='https://calibre-ebook.com/downloads/demos/demo.docx']"); if (link) { const fileUrl = await page.evaluate(el => el.href, link); const response = await fetch(fileUrl); const buffer = await response.buffer(); const fileName = fileUrl.split('/').pop(); await fs.writeFile(`./${fileName}`, buffer); console.log(`文件${fileName}保存成功`); } await browser.close(); }; downloadFile();
方法3:配置浏览器自动下载行为
通过设置浏览器下载路径,让浏览器自动处理下载流程:
const puppeteer = require('puppeteer-extra'); const path = require('path'); const downloadFile = async () => { const downloadPath = path.resolve('./downloads'); const browser = await puppeteer.launch({ headless: true, userDataDir: "./BrowserData", args: [ `--download-path=${downloadPath}`, '--disable-popup-blocking' ] }); const page = (await browser.pages())[0]; // 设置允许下载并指定路径 await page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: downloadPath }); await page.goto("https://www.google.com/search?q=type%3Adocx&sxsrf=ALiCzsYSc2CfabaHQHZdsQMgxFOFv2y0OQ%3A1664557191759&ei=hyA3Y93tLcLY5NoP0oO48A4&ved=0ahUKEwidzf3g_rz6AhVCLFkFHdIBDu4Q4dUDCA4&uact=5&oq=type%3Adocx&gs_lcp=Cgdnd3Mtd2l6EAM6CggAEEcQ1gQQsANKBAhBGABKBAhGGABQpAZYpAZg1AhoAXABeACAATuIATuSAQExmAEAoAEByAEIwAEB&sclient=gws-wiz"); const link = await page.$("a[href='https://calibre-ebook.com/downloads/demos/demo.docx']"); if (link) { await link.click(); // 等待下载完成 await page.waitForTimeout(5000); console.log(`文件已下载至${downloadPath}`); } await browser.close(); }; downloadFile();
内容的提问来源于stack exchange,提问作者Not_A_Carrot
相关产品推荐
相关产品推荐

