#javascript #css #node.js #express #pug
Вопрос:
Я пытаюсь загрузить файл css и изображение в свой файл pug, но ни один из них не загружается. Такое чувство, что я перепробовал все, что мог найти, но не нашел решения. У меня есть css и изображение в общей папке, которая установлена как статическая с помощью express. Я ценю любую помощь, которую могу получить.
Структура папок выглядит следующим образом:
server.js
views
checklist.pug
routes
checklist.js
public
images
logo.png
stylesheets
checklist.css
pdfs
server.js
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const checklists = require('./routes/checklists');
const port = 3000;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// View engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, 'public')));
// Routes
app.use('/checklists', checklists);
app.listen(port, () => {
console.log(`Server started on port ${port}...`);
});
контрольный список.мопс
html(lang='en')
head
link(href='stylesheets/checklist.css' rel='stylesheet')
link(rel='preconnect' href='https://fonts.googleapis.com')
link(rel='preconnect' href='https://fonts.gstatic.com' crossorigin)
link(href='https://fonts.googleapis.com/css2?family=Robotoamp;display=swap' rel='stylesheet')
body
div(class='checklist-title')
img(src='images/logo.png' alt='Logo...')
checklist.js
const express = require('express');
const aws = require('aws-sdk');
const { v4 } = require('uuid');
const puppeteer = require('puppeteer');
const pug = require('pug');
const dynamodb_config = require('../config/dynamodb/dynamo_config');
aws.config.update(dynamodb_config);
const { validateChecklist } = require('../middleware/validation');
const authenticateToken = require('../middleware/authenticateToken');
const router = express.Router();
const docClient = new aws.DynamoDB.DocumentClient();
const TABLE_NAME = 'Checklists';
// Generate html from checklist object, convert to pdf and send in response
router.get('/:id/pdf', authenticateToken, (req, res) => {
// Get the checklist and make sure the user owns it
const params = {
TableName: TABLE_NAME,
Key: {
id: req.params.id
}
}
docClient.get(params, async (err, data) => {
if (err) {
console.error(err);
res.status(500);
res.json({
error: err
});
}
else {
// Check that an item was found
if (typeof data.Item != 'undefined') {
// An item was found
// Check that the user who sent the request is the owner of the item
if (req.username == data.Item.createdBy) {
// CODE TO GENERATE CHECKLIST HERE
try {
const checklist = {
checklist: data.Item
}
// render html
const compiledFunction = pug.compileFile('views/checklist.pug');
const htmlContent = compiledFunction(checklist);
// convert html to pdf and save file
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(htmlContent, { waitUntil: 'networkidle2' });
await page.pdf({ path: `pdfs/${req.username}.pdf`, printBackground: true });
await browser.close();
res.status(200);
res.json({
message: 'success'
});
}
catch (err) {
console.error(err);
}
}
else {
// User does not own the item
console.error('You are not authorized to access that item');
res.status(403);
res.json({
error: 'You are not authorized to access that item'
});
}
}
else {
// No item was found
console.error(`A checklist with id ${req.params.id} could not be found`);
res.status(404);
res.json({
error: `A checklist with id ${req.params.id} could not be found`
});
}
}
});
});
module.exports = router;
Комментарии:
1.
link(href="/stylesheets/checklist.css" rel="stylesheet")
иimg(src="/images/logo.png"
routes
Папка не упоминается в вашей структуре папок. checklist.js не отображается.2. Спасибо @OldGeezer, К сожалению, эти изменения в путях не решили проблему. Извините за недостающую информацию, я обновил вопрос со структурой папок маршрутов и добавил соответствующую информацию из checklist.js. Дай мне знать, что ты думаешь. Я ценю вашу помощь.
3. Я думаю, что проблема может быть в том, в
puppeteer
чем у меня нет опыта. Похоже, что он создает html-страницу из некоторого содержимого файла, а не из веб-URL. Поэтому пути для вложенных папок изображений и таблиц стилей должны быть относительно папки по умолчанию, которая применяется к браузеру приpage.newPage()
вызове. Вы можете попробовать поэкспериментировать, чтобы найти это место, если его нет вpuppeteer
документации.4. То, что делает код, сначала генерирует html из файла pug и моего объекта базы данных, затем загружает этот html в puppeteer (браузер без головы), а затем я, по сути, печатаю эту страницу браузера в pdf. Папка pdf находится в корневой папке проекта. Я обновил свой вопрос, чтобы показать это. Хотя, насколько я понимаю, это ничего не должно изменить. Я думаю, что ваша точка зрения об относительном пути для браузера может быть на что-то похожа, но не сразу понятно, как я мог бы это проверить.
Ответ №1:
Таким образом, проблема в конечном итоге оказалась в том, что кукольник в конце концов, как сказал @OldGeezer. Поскольку я использовал функцию page.setContent() от puppeteer для загрузки html-содержимого непосредственно в браузер вместо указания пути к html-файлу, ни один из относительных путей к моему изображению или css не работал. В итоге я решил эту проблему, используя функцию page.goto(путь) в puppeteer для загрузки пустого html-файла, который я создал в общей папке, а затем используя функцию page.setContent() для загрузки нужного мне html. Это позволило браузеру находиться в нужном каталоге для загрузки внешних файлов по их относительным путям.
server.js
views
checklist.pug
routes
checklist.js
public
empty.html
images
logo.png
stylesheets
checklist.css
pdfs
checklist.js
const express = require('express');
const aws = require('aws-sdk');
const { v4 } = require('uuid');
const puppeteer = require('puppeteer');
const pug = require('pug');
const dynamodb_config = require('../config/dynamodb/dynamo_config');
aws.config.update(dynamodb_config);
const { validateChecklist } = require('../middleware/validation');
const authenticateToken = require('../middleware/authenticateToken');
const router = express.Router();
const docClient = new aws.DynamoDB.DocumentClient();
const TABLE_NAME = 'Checklists';
// Generate html from checklist object, convert to pdf and send in response
router.get('/:id/pdf', authenticateToken, (req, res) => {
// Get the checklist and make sure the user owns it
const params = {
TableName: TABLE_NAME,
Key: {
id: req.params.id
}
}
docClient.get(params, async (err, data) => {
if (err) {
console.error(err);
res.status(500);
res.json({
error: err
});
}
else {
// Check that an item was found
if (typeof data.Item != 'undefined') {
// An item was found
// Check that the user who sent the request is the owner of the item
if (req.username == data.Item.createdBy) {
// CODE TO GENERATE CHECKLIST HERE
try {
const checklist = {
checklist: data.Item
}
// render html
const compiledFunction = pug.compileFile('views/checklist.pug');
const htmlContent = compiledFunction(checklist);
// convert html to pdf and save file
const browser = await puppeteer.launch();
const page = await browser.newPage();
// go to empty html file
await page.goto('file://' __dirname '/../public/empty.html');
await page.setContent(htmlContent, { waitUntil: 'networkidle2' });
await page.pdf({ path: `pdfs/${req.username}.pdf`, printBackground: true });
await browser.close();
res.status(200);
res.json({
message: 'success'
});
}
catch (err) {
console.error(err);
}
}
else {
// User does not own the item
console.error('You are not authorized to access that item');
res.status(403);
res.json({
error: 'You are not authorized to access that item'
});
}
}
else {
// No item was found
console.error(`A checklist with id ${req.params.id} could not be found`);
res.status(404);
res.json({
error: `A checklist with id ${req.params.id} could not be found`
});
}
}
});
});
module.exports = router;