У меня есть приложение 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
🤔 А знаете ли вы, что...
JavaScript позволяет создавать мобильные приложения для iOS и Android с использованием фреймворков, таких как React Native и NativeScript.
Через несколько часов мне удалось найти проблему.
После запуска браузера с журналированием браузера 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.
благодаря ответу @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']