You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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. 尝试1报错原因:

    • 点击文件链接时,浏览器可能触发OPTIONS预检请求,这类请求无响应体,调用response.buffer()必然报错。
    • page.evaluate点击链接后页面跳转,导致响应被中断,无法完整获取文件内容。
  2. 尝试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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:35:19