无法使用node js 将生成的文件下载到电脑

问题描述 投票:0回答:1

Stack Overflow 社区您好,

我目前正在开发一个用作认证系统的 Express.js 应用程序。该应用程序旨在根据参与者的电子邮件地址生成 PDF 格式的个性化证书。

问题: 我在启动从服务器到客户端的文件下载时遇到问题。应用程序成功生成了 PDF 证书,但是当我尝试触发下载时,没有任何反应,文件也没有下载。我正在本地主机上运行该应用程序。

app.js

const fs=require("fs")
const moment=require("moment")
const express=require("express")
const PDFDocument=require("pdfkit")
const QRCode = require("qrcode");
const { createCanvas } = require("canvas");
const csvparse = require("csv-parse");
const path = require('path');

let parsedData; 
const csvData = fs.readFileSync('./data_file/GDSC_MSCW.csv', 'utf8');
const parseCSV = () => {
    return new Promise((resolve, reject) => {
      const parser = csvparse.parse(csvData, { columns: true, delimiter: "," });
      const data = [];
  
      parser.on("data", (row) => {
        data.push(row);
      });
  
      parser.on("end", () => {
        parsedData = data;
        resolve();
      });
  
      parser.on("error", (err) => {
        reject(err);
      });
    });
  };

parseCSV()
    .then(() => {
      console.log("CSV parsing completed");
    })
    .catch((error) => {
      console.error("Error parsing CSV:", error);
    });
  
const app = express();
const port = 3000;
console.log(csvData)
const generateCertificate = async (name,link) => {
const doc=new PDFDocument({
    layout:"landscape",
    size:"A4",
})

const fileName = `${name}.pdf`;
const filePath = path.resolve(fileName);

doc.pipe(fs.createWriteStream(`${name}.pdf`))
doc.image("images/certificate_2.png",0,0,{width:842})
doc.fillColor("#3D3D3D")
doc.font("fonts/OpenSans-Bold.ttf")
doc.fontSize(29).text(name,249,157,{
align:"left",
})
const qrCodeDataURL = await QRCode.toDataURL(link, {
    version: 6, // QR code version
});
doc.image(qrCodeDataURL, 738, 497, { width: 70 });
doc.end()

return filePath;

}


app.use(express.static(path.join(__dirname, 'public')));

app.get("/getUserInfo", async (req, res) => {
  const userEmail = req.query.email;
  console.log("Hello");

  const user = parsedData.find((entry) => entry.Email === userEmail);

  if (user) {
      try {
          const filePath = await generateCertificate(user.Name, user.ProfileLink);
      res.download(filePath, (err) => {
        if (err) {
          console.error('Error sending file:', err);
          res.status(500).json({ success: false, error: 'Internal Server Error' });
        } else {
          console.log('Download Completed');
          fs.unlinkSync(filePath);
        }
      });
        } catch (error) {
          console.error('Error generating certificate:', error);
          res.status(500).json({ success: false, error: 'Internal Server Error' });
      }
  } else {
      res.status(404).json({
          success: false,
          message: "Unable to find participant, please make sure you input the correct email id",
      });
  }
});


  
app.get('/', (req, res) => {
    const indexPath = path.join(__dirname, 'index.html');
    res.sendFile(indexPath);
});
app.listen(port, () => {
    console.log(`Server is running at http://localhost:${port}`);
});

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GCSJ 2023</title>
    <!-- Bootstrap CSS -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <!-- Font Awesome for icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css">
    <!-- Custom styles -->
    <style>
        body {
            display: flex;
            flex-direction: column;
            min-height: 100vh;
        }

        #header-image {
            width: 100%;
        }

        #content {
            flex-grow: 1;
        }

        .form-container {
            text-align: center;
            padding: 20px;
        }

        .form-group {
            margin-bottom: 20px;
        }

        #social-icons {
            text-align: center;
            margin-top: 20px;
        }

        #footer {
            text-align: center;
            padding: 20px;
            background-color: #f8f9fa; /* Light background color */
        }
    </style>
</head>
<body class="container">

    <!-- Header Image -->
    <img src="header_.png" alt="Header Image">

    <div id="content">

        <h1 class="text-center mt-4 mb-4">Certification 2023-24</h1>

        <!-- Form -->
        <div class="form-container">
            <form id="userForm">
                <div class="form-group">
                    <label for="email" class="sr-only">Enter your email:</label>
                    <input type="email" class="form-control form-control-lg" id="email" placeholder="Enter your email" required>
                </div>
                <button type="button" class="btn btn-primary btn-lg" onclick="getUserInfo()">Generate Certificate</button>
            </form>
        </div>

        <!-- Social Icons -->
        <div id="social-icons">
            <a href="your-social-link" target="_blank" title="YouTube"><i class="fab fa-youtube fa-2x ml-2" style="color: red;"></i></a>
            <a href="your-social-link" target="_blank" title="Twitter"><i class="fab fa-twitter fa-2x ml-2" style="color: rgb(0, 144, 201);"></i></a>
            <a href="your-social-link" target="_blank" title="Instagram"><i class="fab fa-instagram fa-2x ml-2" style="color: rgb(206, 45, 72);"></i></a>
            <a href="your-social-link" target="_blank" title="LinkedIn"><i class="fab fa-linkedin fa-2x ml-2" style="color: rgb(67, 67, 255);"></i></a>

            <!-- Add more social icons as needed -->
        </div>

    </div>

    <!-- Footer -->
    <div id="footer">
        <p>&copy; 2023 XYZ. All rights reserved.</p>
    </div>
    <!-- Font Awesome JS -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/js/all.min.js"></script>

    <script>
         function handleResponse(response) {
    if (response.success) {
      // If success, show an alert with the message
      alert(response.message);

      // Optionally, you can initiate the file download using JavaScript
      // For example, redirect the browser to the download link
      window.location.href = `/download/${response.fileName}.pdf`;
    } else {
      // If not success, show an alert with the error message
      alert(response.message);
    }
  }
        async function getUserInfo() {
            const email = document.getElementById('email').value;
            try {
                const response = await fetch(`/getUserInfo?email=${encodeURIComponent(email)}`).then(response => response.json()).then(data => handleResponse(data)).catch(error => console.error('Error:', error));
                const data = await response.json();
            } catch (error) {
                console.error('Error fetching user data:', error);
            }
        }
    </script>

</body>
</html>
node.js express file server download
1个回答
0
投票

在您的 HTML 文件中,您尝试使用以下行启动下载

window.location.href = `/download/${response.fileName}.pdf`;

但是在 Express.js 应用程序中,您将路由定义为 /getUserInfo,而不是 /download。您需要确保 HTML 中的路由与服务器中定义的路由匹配。
此外,您还使用 .then() 和 async/await 来处理异步操作。为了保持 getUserInfo 函数的一致性,您可以只使用 async/await。

const response = await fetch(`/getUserInfo?email=${encodeURIComponent(email)}`);
const data = await response.json();
handleResponse(data);
© www.soinside.com 2019 - 2024. All rights reserved.