Почему создание PDF-файлов Puppeteer не работает в Windows?

У меня есть приложение NodeJs, которое пытается создать PDF-файл из HTML. Он работает на Mac, но не на Windows (время истекло). Вот код.

const puppeteer = require('puppeteer');
const fs = require('fs');

const init = async () => {
    try {
        const browser = await puppeteer.launch({headless: true});
        const page = await browser.newPage();

        await page.setContent('<h1>Hello World</h1>');
        await page.emulateMediaType('screen');
        await page.pdf({
            path: 'hello-world.pdf',
            format: 'A4',
            printBackground: true,
            timeout: 0
        });

        console.info('PDF Generated');
        await browser.close();
        process.exit()

    } catch (error) {
        console.info(error)
    }
};

init()

после вызова метода page.pdf он ждет так долго и истекает время ожидания. ProtocolError: Page.printToPDF timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.

Но на моем MacBook Pro M1 это работает просто великолепно.

Попробовал это на виртуальной машине Windows 11 (Parallels) и паре ноутбуков с Windows 11. Но не повезло.

Что я здесь делаю не так? Нужно ли мне добавить что-то еще?

Спасибо!

Узел: v20.15.0

Кукловод: ^22.12.1

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
148
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Через несколько часов мне удалось найти проблему.

После запуска браузера с журналированием браузера await puppeteer.launch({headless: true, dumpio:true}); было записано следующее:

[16848:6956:0703/000025.226:ERROR:sandbox_win.cc(913)] Sandbox cannot access executable. Check filesystem permissions are valid. See [URL]: Access is denied. (0x5)

DevTools listening on ws://[URL][16848:7356:0703/000025.488:ERROR:network_service_instance_impl.cc(600)] Network service crashed, restarting service.
[16848:6956:0703/000026.330:ERROR:sandbox_win.cc(913)] Sandbox cannot access executable. Check filesystem permissions are valid. See [URL]: Access is denied. (0x5)

поэтому мне удалось найти добавление args: ['--no-sandbox', '--disable-setuid-sandbox'] - это обходной путь, но не рекомендуется https://stackoverflow.com/a/53975412/9814969

const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); сработало!

Кажется, это обычная проблема в системах на базе Linux, но я пробовал это в Windows. Поэтому добавив это как ответ

Ответ принят как подходящий

Основываясь на журнале io из вашего собственного ответа, я не уверен, что вы действительно смогли увидеть [URL], который он выводит на консоль, но он ведет к этой документации Chromium Sandbox , в которой указано, что вам, возможно, придется установить необходимые разрешения самостоятельно в зависимости от способа установки. Это может произойти при использовании Puppeteer в Windows. По сути, это также было скопировано в Устранение неполадок Puppeteer, где также можно установить необходимые разрешения с помощью icacls.

По моему мнению, это более безопасный способ, чем просто полное отключение песочницы. Однако SID, используемый в предоставленной команде S-1-15-2-1, приводит к ALL APPLICATION PACKAGES, что довольно широко. Вот почему в обоих документах упоминается, что «в средах с высоким уровнем безопасности следует использовать более строгий SID, например, идентификатор установщика» (я почти уверен, что предоставленная ссылка на установщик на самом деле ссылается на неправильный LOC и на самом деле должна вести до здесь ). Однако в документации Chromium Sandbox упоминается ALL RESTRICTED APPLICATION PACKAGES SID (Windows 10 RS2 или более поздняя версия), который не отображается в официальном списке Microsoft «Хорошо известных SID», но есть S-1-15-2-2.

Решение. Вот почему я думаю, что вместо отключения песочницы было бы безопаснее предоставить необходимые разрешения, выполнив следующую команду в CMD:

icacls %USERPROFILE%/.cache/puppeteer/chrome /grant *S-1-15-2-2:(OI)(CI)(RX)

Запуск cmd от имени администратора не требуется (по крайней мере, у меня). Путь — это место, где Puppeteer обычно хранит свои корзины Chrome, но вам может потребоваться изменить его, если вы указали другой путь в Puppeteer.

Дело в том, что S-1-15-2-2 по-прежнему является довольно широким SID, но мне не удалось найти более узкий SID, который бы работал. Если вы проверите установщик , вы увидите, что он устанавливает GENERIC_READ (GR) и FILE_DELETE_CHILD (DC) для SID AUTHENTICATED_USERS, однако этого не может быть всего, потому что LOC в "sandbox_win.cc" выдает вашу ошибку на самом деле проверяет GENERIC_READ (GR) и GENERIC_EXECUTE (GE) (всего (RX)). Я почти уверен, что идентификаторы безопасности пользователей и группы SID не будут работать. Я думаю, что подойдет SID для входа в систему, начинающийся с S-1-5-5-, но он будет меняться каждый раз. Я еще немного поиграюсь с информацией, найденной в этом ответе, и отредактирую его, если найду более безопасное решение. Кроме того, я даже не понимаю, почему SID пакетов работают, потому что они должны работать только для приложений Магазина Windows, процессов, запущенных в контейнере приложений или UWP. Так что это определенно не приложение из Магазина Windows. Я также проверил с помощью Process Explorer, и рассматриваемый процесс не запускается в контейнере приложения. Я не мог убедиться, что Chromium для Windows является UWP.

Вау, спасибо за подробный ответ! Это было для личного проекта, после того как я нашел исправление (отключение песочницы), мне было лень искать подходящее исправление для этого. Еще раз спасибо, я обновлю свой проект после тестирования.

ChethiyaKD 22.07.2024 11:56

Не волнуйтесь, я столкнулся с той же проблемой, и это сводило меня с ума.

Fiddlesteaks 22.07.2024 12:44

Отметил ваш ответ как принятый

ChethiyaKD 29.07.2024 09:26

благодаря ответу @Fiddlesteaks мне пришлось запустить обе эти команды:

icacls $env:USERPROFILE/.cache/puppeteer/chrome-headless-shell /grant *S-1-15-2-2":(OI)(CI)(RX)"

icacls $env:USERPROFILE/.cache/puppeteer/chrome /grant *S-1-15-2-2":(OI)(CI)(RX)"

тогда генерация PDF работает без args: ['--no-sandbox', '--disable-setuid-sandbox']

Другие вопросы по теме