Puppeteer - 如何设置下载位置

puppeteer - how to set download location

提问人:A. L 提问时间:10/27/2017 最后编辑:A. L 更新时间:2/16/2023 访问量:27219

问:

我能够使用 puppeteer 成功下载文件,但它只是将其保存到我的 /Downloads 文件夹中。我一直在四处寻找,在 api 或论坛中找不到任何可以设置此位置的内容。

我的下载基本上只是去链接:

await page.goto(url);
节点 .js 木偶师

评论

0赞 Abdullah Alsigar 10/27/2017
目前还没有论据。您是否尝试在用户数据目录中修改它?
0赞 A. L 10/27/2017
@AbdullahAlsigar对不起,我应该修改什么?
0赞 Abdullah Alsigar 10/27/2017
我现在不在我的电脑上,不确定到底是什么。对不起。
0赞 A. L 10/27/2017
@AbdullahAlsigar,当你回到电脑前时,只要让我知道你在哪里,你还记得这个问题,哈哈
0赞 Abdullah Alsigar 10/28/2017
我在配置文件文件夹中找不到任何内容。另一个建议是在 Headless: false 中运行 Puppeteer,然后设置默认下载文件夹,我认为这应该可以解决问题。

答:

38赞 Md. Abu Taher 11/15/2017 #1

更新的 Puppeteer 版本(~2022 年 6 月):

正如@Daniel在这里提到的,您必须自己创建 CDP 会话:

const client = await page.target().createCDPSession()
await client.send('Page.setDownloadBehavior', {
  behavior: 'allow',
  downloadPath: './myAwesomeDownloadFolder',
})

原始答案

这是在最新的 Puppeteer v0.13 中设置下载路径的方法。

await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './myAwesomeDownloadFolder'});

该行为是实验性的,以后可能会被删除、修改或更改。

Pst,您可以尝试此处列出的更多技巧,风险自负:)。

评论

0赞 Janusz01 3/7/2020
无法更改下载文件夹。我将此行放在下载操作之前并提供绝对下载路径。我做错了什么?
0赞 Md. Abu Taher 3/7/2020
在某个地方共享你的代码,可能在 github gist 中。
3赞 Muhammad Uzair 7/28/2022
更新:2022 不是一个函数,所以它不起作用._client
0赞 titoih 10/26/2022
._client不起作用(在 2022 年),它应该是 .client
1赞 Oliver Zhang 5/9/2023
谢谢!我花了半天时间试图从 ChatGPT 中获取信息。但这就是有效的!
4赞 ara6893 12/3/2020 #2

我意识到这是一个旧线程,但是在寻找如何设置 Puppeteer 默认下载位置时,我首先弹出了这个线程。 我能够使用以下代码设置下载位置,

let customChrome = path.resolve(__dirname, './customChrome')
        let prefs = fs.readFileSync(customChrome+'/Default/Preferences');
        let obj = JSON.parse(prefs);
        obj.savefile.default_directory = path.resolve(__dirname, './downloads');
        obj.download.default_directory = path.resolve(__dirname, './downloads');
        fs.writeFileSync(customChrome+'/Default/Preferences', JSON.stringify(obj));
        const browser = await puppeteer.launch({
            userDataDir:customChrome,
            headless: false,                                                                                                                                                                                                                                                 
            args:['--disable-features=site-per-process','--no-sandbox']
        });

这将在进程开始之前设置文件的默认下载目录。从本质上讲,Puppeteer 每次运行时都会创建一个自定义配置文件,我们可以覆盖该配置文件并定义下载目录。

首次运行上述代码时,您必须将 fs.readFile 注释掉为 fs.writeFile,因为 UserDirDirectory 在首次启动 Chrome 时不存在。

然后,所有与配置文件相关的数据都存储在 customChrome/Default 文件夹中。如何将 userDataDir 配置文件文件夹传递给 Puppeteer

21赞 Daniel Diekmeier 6/21/2022 #3

在较新版本的 Puppeteer 中(我使用的是 v14.1),接受的答案不再有效:

await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './myAwesomeDownloadFolder'});

> TypeError: page._client.send is not a function

相反,我必须显式创建一个新的 CDPSession

const client = await page.target().createCDPSession()
await client.send('Page.setDownloadBehavior', {
  behavior: 'allow',
  downloadPath: './myAwesomeDownloadFolder',
})

评论

2赞 Sam 6/24/2022
英雄。无法让 API 按预期工作——这可能是这里公认的答案。fileChooser
0赞 Ryan D 8/3/2022
当我使用此代码时,浏览器无法下载文件并弹出错误消息:没有此代码即可正常下载,并且文件保存到 Windows 上的 Downloads 文件夹。有什么想法吗?headless=falseSomething went wrong.
0赞 JohanR 8/16/2023
@RyanD 在 Windows 上,您需要使用双反斜杠才能使路径正常工作。这对我有用downloadPath: "F:\\download\\puppeteer"
1赞 Muhammad Uzair 7/28/2022 #4

所有给定的解决方案在较新版本的 puppeteer 中都不适合我15.5.0

与插件一起使用就成功了。puppeteer-extrapuppeteer-extra-plugin-user-preferences

// make sure puppeteer-extra & puppeteer-extra-plugin-user-preferences are installed

const UserPreferencesPlugin = require("puppeteer-extra-plugin-user-preferences");

const downloadImageDirectoryPath = process.cwd()

puppeteer.use(
  UserPreferencesPlugin({
    userPrefs: {
      download: {
        prompt_for_download: false,
        open_pdf_in_system_reader: true,
        default_directory: downloadImageDirectoryPath,
      },
      plugins: {
        always_open_pdf_externally: true,
      },
    },
  })
);

-1赞 Patryk K 7/30/2022 #5

2022 年 7 月 30 日更新: 已进行更新,并且此功能也已从软件包的先前版本中删除,如果您在 2022 年 6 月 10 日之前下载了该软件包,它应该可以工作。对我来说就是这样,但令人费解的是,为什么以前的版本也被更改了......

评论

0赞 Community 8/2/2022
您的答案可以通过其他支持信息进行改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。
2赞 KBoicourt 8/4/2022 #6

Muhammad Uzair 的回答解决了我设置 Chromium 用户首选项以强制下载 PDF 文件的类似问题,但我遇到了设置问题,因为我使用的是 Puppeteer、Jest 和 Jest-Puppeteer,其中 Jest-Puppeteer 在幕后处理初始设置。

Macil 的这篇 Github 帖子有助于如何在文件中应用 puppeteer-extra-plugin-user-preferences 插件。jest-puppeteer.config.js

例如,这是我的文件:jest-puppeteer.config.js

const puppeteer = require('puppeteer-extra');
const UserPreferencesPlugin = require('puppeteer-extra-plugin-user-preferences');

const userPreferenceOptions = {
  userPrefs: {
    plugins: {
      always_open_pdf_externally: true,
    },
    download: {
      open_pdf_in_system_reader: false,
      prompt_for_download: false,
    },
  }
};
puppeteer.use(UserPreferencesPlugin(userPreferenceOptions));

require.cache[require.resolve('puppeteer')] = require.cache[require.resolve('puppeteer-extra')];

module.exports = {
  launch: {
    // https://github.com/puppeteer/puppeteer/blob/v13.3.2/docs/api.md#puppeteerlaunchoptions
    headless: true, // opens a browser instance
    slowMo: 25, // millis to slow each step
    devtools: false, // auto opens the devtools in the browser
    defaultViewport: {
      width: 1820,
      height: 980,
      deviceScaleFactor: 1,
      isMobile: false,
      isLandscape: true,
    },
    product: "chrome", // can also specify firefox
    browserContext: 'incognito',
    args: [
      // Chromium browser arguments: https://peter.sh/experiments/chromium-command-line-switches/
      '--ignore-certificate-errors',
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--window-size=1920,1080',
    ],
  },
};

0赞 Eric Y 9/1/2022 #7

最后,我在安装了 chrome 的 docker 容器中运行该程序

FROM node:18-slim

# ------------------------------------------
# install extension
# ------------------------------------------
RUN apt-get update -y && apt-get install -y \
    # chromium \
    # libnss3 lsb-release xdg-utils wget \
    wget gnupg \
    && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
    && apt-get update \
    && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

# ------------------------------------------
# set global config
# ------------------------------------------
ENV TZ Asia/Hong_Kong
# ------------------------------------------
# change the work directory
# ------------------------------------------
COPY source /root/source
WORKDIR /root/source

# ------------------------------------------
# upgrade npm
# ------------------------------------------
RUN npm install npm -g
RUN npm upgrade

# install node packages
RUN if test -e package-lock.json ; then npm ci ; else npm i ; fi
RUN npm run build
ENTRYPOINT ["npm", "run"]
CMD ["start"]

用作下载文件的客户端 ( 编号: https://github.com/puppeteer/puppeteer/issues/1478#issuecomment-358826932 https://pptr.dev/api/puppeteer.cdpsessionawait page.target().createCDPSession() )

const downloadPath = `[YOU OWN DOWNLOAD PATH]`
const browser = await puppeteer.launch({
  headless: true,
  args: ['--no-sandbox', '--disable-setuid-sandbox'],
  executablePath: '/usr/bin/google-chrome-stable'
})

const page = await browser.newPage()
const client = await page.target().createCDPSession()
await client.send('Page.setDownloadBehavior', {
  behavior: 'allow',
  downloadPath
})