#javascript #node.js #puppeteer
#javascript #node.js #кукловод
Вопрос:
Допустим, у меня есть холст в HTML-файле (ничего особенного). И я использую Puppeteer, чтобы нарисовать что-то на холсте в контексте браузера, а затем передать это в контекст NodeJS, где я сохраняю это как PNG-файл, используя OpenCV.
Поскольку двоичные данные не могут быть переданы между двумя контекстами (браузер и узел), я должен преобразовать двоичные данные в строку и восстановить двоичные данные в узле. Следующий код делает именно это:
const puppeteer = require('puppeteer');
const cv = require('opencv4nodejs');
const pup = puppeteer.launch({
headless: false,
args: [
'--use-gl=swiftshader',
'--no-sandbox',
'--enable-surface-synchronization',
'--disable-web-security',
]
}).then(async browser => {
const page = (await browser.pages())[0];
page.on('console', msg => console.log(msg.text()));
page.on("pageerror", function(err) {
const theTempValue = err.toString();
console.log("Page error: " theTempValue);
});
page.on("error", function (err) {
const theTempValue = err.toString();
console.log("Error: " theTempValue);
});
await page.exposeFunction('_setupCompleted', async () => {
await page.evaluate(async () => {
const c = document.getElementById("myCanvas");
const dataUrl = c.toDataURL("image/png");
const txt = await new Promise(resolve => c.toBlob((blb) => blb.text().then(resolve), "image/png"));
await window._saveMat(dataUrl, txt);
});
await browser.close();
});
await page.exposeFunction('_saveMat', async (dataUrl, txt) => {
dataUrl = dataUrl.replace(/^data:image/png;base64,/, "");
const dataUrlBuffer = Buffer.from(dataUrl, 'base64');
const dataUrlMat = cv.imdecode(dataUrlBuffer, -1);
cv.imwrite(`./dataUrl.png`, dataUrlMat);
const txtBuffer = Buffer.from(txt, 'utf8');
const txtMat = cv.imdecode(txtBuffer, -1);
cv.imwrite(`./txtMat.png`, txtMat);
});
await page.goto('http://127.0.0.1:8887/index.html', {
waitUntil: 'networkidle2',
});
});
В данном коде я передаю PNG двумя способами. Сначала я использую toDataURL
метод canvas. Этот метод кодирует двоичные данные canvas с использованием base64 и добавляет к нему некоторую подпись. После получения код в Node удалит подпись и декодирует base64. Эта часть кода работает отлично, и она отлично сохраняет PNG.
Другой подход использует toBlob
метод canvas. Этот метод возвращает большой двоичный объект, который я вызову его text
методом, чтобы преобразовать его в строку. На стороне узла я попытаюсь восстановить буфер из переданной строки. Эта часть не выполняется. По-видимому, восстановленный буфер не является допустимым PNG, и imdecode
методу не удается создать объект mat на его основе.
Мой вопрос в том, как я могу восстановить тот же буфер, который я получаю от toDataURL
использования текста, который я получаю от toBlob
метода в NodeJS?
Комментарии:
1. Не преобразуйте большой двоичный объект в
text
, процесс кодирования почти наверняка повредит некоторые кодовые точки, поскольку это двоичный, а не закодированный текст.2. @PatrickRoberts Спасибо. Означает ли это, что я застрял с
toDataURL
?3. Нет, вы должны использовать
arrayBuffer()
вместоtext()
и создаватьBuffer
непосредственно из него, не указывая кодировку, поскольку это необработанные двоичные данные.