skip to Main Content

This is my node js server code. For some reason my images don’t load. Any help please?
At one time it worked, but all requests gave the same images, no matter what image I had in the folder

const express = require("express");
const fs = require("fs");
const { v4: uuidv4 } = require("uuid");
const multer = require("multer");
const path = require("path");

const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());
app.use(express.static("public"));

// Create chatbot
app.get("/create", (req, res) => {
  const chatbotId = uuidv4();
  const chatbotFolderPath = `public/chatbots/${chatbotId}`;

  // Create a folder for the new chatbot
  fs.mkdirSync(chatbotFolderPath, { recursive: true });

  // Copy the template to the new chatbot folder
  fs.copyFileSync(
    "public/templates/chatbot_template.html",
    `${chatbotFolderPath}/index.html`
  );

  // Copy the images folder
  fs.mkdirSync(`${chatbotFolderPath}/images`);
  fs.readdirSync("public/templates/images").forEach((file) => {
    fs.copyFileSync(
      `public/templates/images/${file}`,
      `${chatbotFolderPath}/images/${file}`
    );
  });

  // Copy the colors.json file
  fs.copyFileSync(
    "public/templates/colors.json",
    `${chatbotFolderPath}/colors.json`
  );

  // Copy the bot_info.json file
  fs.copyFileSync(
    "public/templates/bot_info.json",
    `${chatbotFolderPath}/bot_info.json`
  );

  res.send(`Your unique chatbot ID is: ${chatbotId}`);
});

// Serve static files for all chatbots
/* app.use("/images/:chatbotId", (req, res, next) => {
  const { chatbotId } = req.params;
  const chatbotImagesPath = `public/chatbots/${chatbotId}/images`;
  express.static(chatbotImagesPath)(req, res, next);
}); */

/* app.use(
  "/images/:chatbotId",
  express.static(path.join(__dirname, "public/chatbots"))
); */

// View chatbot
app.get("/:chatbotId", (req, res) => {
  const { chatbotId } = req.params;
  const chatbotFilePath = `public/chatbots/${chatbotId}/index.html`;

  // This makes sure the user can get the images
  // Bug: This app.use is updated every time a chatbot is created, so only the
  // most recently created chatbot's images will be available for use
  app.use(
    "/images",
    express.static(__dirname + `/public/chatbots/${chatbotId}/images`)
  );

  // http://localhost:3000/images/a3cfb70c-16ee-4557-be19-cf15ed1b3348/logo.jpg
  /*  app.use("/images/:chatbotId", (req, res, next) => {
    const { chatbotId } = req.params;
    const chatbotImagesPath = `public/chatbots/${chatbotId}/images`;
    express.static(chatbotImagesPath)(req, res, next);
  }); */

  fs.access(chatbotFilePath, fs.constants.F_OK, (err) => {
    if (err) {
      res.status(404).send("Chatbot not found");
    } else {
      res.sendFile(__dirname + `/public/chatbots/${chatbotId}/index.html`);
    }
  });
});

// Upload
const upload = multer({ dest: "public/uploads/" });
app.post("/upload", upload.single("logo"), (req, res) => {
  // req.file contains information about the uploaded file
  const uploadedLogo = req.file;

  // Move the uploaded file to the appropriate location (e.g., chatbot folder)
  const chatbotId = req.body.chatbotId; // Assuming you have a way to associate the logo with a chatbot
  const chatbotFolderPath = `public/chatbots/${chatbotId}`;
  const logoPath = `${chatbotFolderPath}/images/logo.jpg`; // Define the path for the logo

  fs.rename(uploadedLogo.path, logoPath, (err) => {
    if (err) throw err;
    res.send("Logo uploaded successfully!");
  });
});

// Color scheme

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

This is an example of I try to get the images inside

<div class="company">
            <img src="./images/logo.jpg" alt="company-logo" />
            <h3 id="company-name">Your Company</h3>
          </div>

I have been debugging this for 2 hours but I can’t seem to wrap my head around it

2

Answers


  1. Chosen as BEST ANSWER
    const chatbotsDirectory = path.join(__dirname, "public/chatbots");
    app.use(express.static(chatbotsDirectory));
    app.use("/images", express.static(path.join(chatbotsDirectory, "images")));
    
    app.get("/:chatbotid", (req, res) => {
      const chatbotId = req.params.chatbotid;
      const chatbotPath = path.join(chatbotsDirectory, chatbotId, "index.html");
    
      res.sendFile(chatbotPath);
    });
    

    This solution works perfectly.


  2. You could handle multiple chatbotId values by supplying more than one middleware function argument to app HTTP request methods such as app.get. A third argument passed to all middleware functions is usually named next in code. Calling it invokes the next middleware function provided to the app method.

    In the example below, app.get first checks if the chatbox exists, and sends an error response if it doesn’t, or calls next if it does.
    The second handler in the route simply calls express.static to serve files from the correct chatbot folder. In express the default file served for a request with no filename is index.html (which can be changed in express configuration) so special handling for an index file may not be required.

    Example:

    // GET request:
    
    app.get("/:chatbotId", (req, res, next) => {
    
        const chatbotId = req.params;;
        const chatbotFilePath = __dirname + `/public/chatbots/${req.params}`;
    
        fsPromises.access(chatbotFilePath, fsPromises.constants.F_OK)
        .then( next)  // see update note below
        .catch ( err => {
           res.status(404).send("Chatbot not found");
         });
      },
    
      // the second middleware function:
      express.static(__dirname + `/public/chatbots/${req.params}`)
    );
    
    • Please research Express and Node documentation for further technical information as required.
    • The code above uses the same chat bot file path in both middleware functions. Please check if it is correct.
    • The first middleware function uses fsPromises.access (not fs.access) to asynchronously check if the chatbot folder exists.
    • The UPDATE middleware will require changes to its design to handle multiple chatbotId ids as well.

    Update Note:

    As I understand it, express.server resolves the req.url against the base folder path provided as its argument. Hence you probably need to adjust req.url to remove the chatbot: component before using it, fairly easily accomplished in the then clause after the fsPromises call by replacing

    .then( next)
    

    with

    .then (()=> {
         req.url = req.url.slice( "/:chatbotId".length);
         next();
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search