如何在客户端请求端点时创建 PDF 并下载它

How to create a PDF and download it when the endpoints is requested by client

我正在用 NodeJS 和 Express 构建一个 API。 IT 是关于产品的市场。我最近开始实施名为 PDFMake 的 PKG,但我遇到了让它工作的问题。我想做的是,当我到达终点 URL/api/v1/products/:id/exportToPdf 时,我应该创建包含产品信息的 PDF 并下载它。这在邮递员中不起作用我看到一个错误 "message": "The value \"product.pdf\" is invalid for option \"encoding\"" 我找不到我想要实现的解决方案,需要帮助以了解如何解决它。

我正在分享使用它的部分:

路由器:

// GET one Product and Export to PDF
router.get("/:id/exportToPDF", check.isValidId, check.rules, async (req, res) => {
    const id = req.params.id;
    const description = req.body.description;
    const name = req.body.name;
    const brand = req.body.brand;
    const category = req.body.category;
    const price = req.body.price;
    await product
        .getOneProductExportToPdf(id, description, name, brand, category, price)
        .then(data =>
            // OK
            res.status(201).json({
                message: `PDF Created`,
                content: data
            })
        )
        .catch(err => {
            if (err.status) {
                res.status(err.status).json({ message: err.message });
            } else {
                res.status(500).json({ message: err.message });
            }
        });
});

型号

// GET One Product PDF Export
const getOneProductExportToPdf = (id, description, name, brand, category, price) => {
    return new Promise((resolve, reject) => {
        helper
            .mustBeInArray(products, id)
            .then(product => {
                const dd = {
                    content: [
                        { text: "Product Info", style: "header" },
                        { text: `${id}`, style: "subheader" },
                        { text: `${description}`, style: "subheader" },
                        { text: `${name}`, style: "subheader" },
                        { text: `${brand}`, style: "subheader" },
                        { text: `${category}`, style: "subheader" },
                        { text: `${price}`, style: "subheader" }
                    ]
                };

                var fonts = {
                    Roboto: {
                        normal: "Helvetica",
                        bold: "Helvetica-Bold",
                        italics: "Helvetica-Oblique",
                        bolditalics: "Helvetica-BoldOblique"
                    }
                };

                const printer = new PdfPrinter(fonts);

                const pdfDoc = printer.createPdfKitDocument(dd, {})

                pdfDoc.pipe(
                    fs.createReadStream(f.uploadsDir, "product.pdf")
                )

                pdfDoc.end();

                resolve(pdfDoc);
            })
            .catch(err => reject(err));
    });
};

f.uploadsDir 只是指向我要在服务器上上传 PDF 的文件夹

// GET one Product and Export to PDF
router.get("/:id/exportToPDF", check.isValidId, check.rules, async (req, res) => {
    const id = req.params.id;
    const description = req.body.description;
    const name = req.body.name;
    const brand = req.body.brand;
    const category = req.body.category;
    const price = req.body.price;
    await product
        .getOneProductExportToPdf(id, description, name, brand, category, price)
        .then(pdfDoc =>{
            // Will get downloaded
            res.setHeader('Content-Type', 'application/pdf');
            res.setHeader('Content-Disposition', 'attachment; filename=product.pdf');
            pdfDoc.pipe(res);
            pdfDoc.end();
        })
        .catch(err => {
            if (err.status) {
                res.status(err.status).json({ message: err.message });
            } else {
                res.status(500).json({ message: err.message });
            }
        });
});

// GET One Product PDF Export
const getOneProductExportToPdf = (id, description, name, brand, category, price) => {
    return new Promise((resolve, reject) => {
        helper
            .mustBeInArray(products, id)
            .then(product => {
                const dd = {
                    content: [
                        { text: "Product Info", style: "header" },
                        { text: `${id}`, style: "subheader" },
                        { text: `${description}`, style: "subheader" },
                        { text: `${name}`, style: "subheader" },
                        { text: `${brand}`, style: "subheader" },
                        { text: `${category}`, style: "subheader" },
                        { text: `${price}`, style: "subheader" }
                    ]
                };

                var fonts = {
                    Roboto: {
                        normal: "Helvetica",
                        bold: "Helvetica-Bold",
                        italics: "Helvetica-Oblique",
                        bolditalics: "Helvetica-BoldOblique"
                    }
                };

                const printer = new PdfPrinter(fonts);

                const pdfDoc = printer.createPdfKitDocument(dd, {})

                resolve(pdfDoc);
            })
            .catch(err => reject(err));
    });
};

它不会在服务器中创建 product.pdf,而是直接在响应中流式传输 pdf。也可以在邮递员中使用 'Save Response' 下载 pdf 文件(以防您无法预览回复)