Почему у меня картинка не отображаеться в елементах?

Картинку отправляю на сервер, а там она undefined, но на cloudinary загрузилась url и есть картинка. HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <!--Для кнопок шрифт-->
    <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=Kablammo&display=swap" 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=Rubik+Gemstones&display=swap" rel="stylesheet">
    <!--Шрифт для іншого тексту-->
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!--CSS-->
    <link rel="stylesheet" href="bg.css">
    <link rel="stylesheet" href="buttons.css">
    <link rel="stylesheet" href="menu.css">
    <link rel="stylesheet" href="modal.css">
    <link rel="stylesheet" href="workmenu.css">
    <link rel="stylesheet" href="item.css">
    <!--CSS-->
    <title>Мережеві накопичувачі</title>
</head>
<body>
        <!--Модальне вікно-->
<form name="productForm" action="/products" method="POST" id="modalform" enctype="multipart/form-data">
    <div class="conteinar" id="modalcont">
        <div class="head">
            <p class="text-h">
               Create NAS
            </p>
            <div class="btn-grid">
                
                <input type="submit" value="X" id="btn-close" onclick="event.preventDefault(); Modaleclose()">
            </div>
        </div>
        <div class="center">
            <input type="hidden" name="productId" id="productId">
                <input type="hidden" name="oldCloudinaryPublicId" id="oldCloudinaryPublicId">
                <input type="hidden" name="oldImagePath" id="oldImagePath">
            <p class="text-p">
                Модель NAS:
            </p>
            <input class="text-field" id="js-input-model" maxlength="30" name="productName" placeholder="Введіть модель NAS" type="text">
            <p class="text-p">
                Модель процесора:
            </p>
            <input class="text-field" id="js-proc" maxlength="30" name="productProc" placeholder="Введіть модель процесора" type="text">
            <p class="text-p">
                Оперативна пам'ять:
            </p>
            <input class="text-field" id="js-op" min="1" max="9999" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" name="productOp" placeholder="Введіть оперативну пам'ять в ГБ" type="number">
            <p class="text-p">
                Ціна:
            </p>
            <input class="text-field" id="js-lan" min="1" max="99999" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" name="productLan" placeholder="Введіть ціну" type="number">
            <p class="text-p">
                Слоти для дисків:
            </p>
            <select name="productDisk" id="js-disk" class="select-t">
                <option class="text-field" value="1">1</option>
                <option class="text-field" value="2">2</option>
                <option class="text-field" value="3">3</option>
                <option class="text-field" value="4">4</option>
            </select>
            <p class="text-p" style="padding-bottom: 10px;">
                Виберіть файл зображення:
            </p>
            <input class="file" name="productImage" type="file" id="productImage" accept=".jpeg, .jpg, .png">
            <button type="submit" id="submitBtn" onclick="modalpush(); event.preventDefault();" value="Confirm" class="buttonedit">Confirm</button>
        </div>
    </div>
</form>
<div class="grey" onclick="Modaleclose();" id="greybg"></div>
    <!--Модальне вікно-->
    <!--menu-->
    <div class="menu">
        <div class="nameshop">
            <b>NAS SHOP</b>
        </div>
                <div class="search"><input type="search" class="searchfield" placeholder="Search your NAS"/></div>
                <div class="green"><button class="green-button">Search</button></div>
    </div>
    <!--workmenu-->
    <div class="workmenu">
        <div class="Manage-nas"><b>Manage NAS</b></div>
        <div>
            <button type="submit" class="create-button" onclick="Modaleshow()">Create</button>
        </div>
        <div class="switch-elements">
            <div class="sort-text">
                <b>Sort by price</b>
            </div>
            <div>
                <div class="switch-div">
            <label class="switch">
                <input type="checkbox" id="sortcheckbox">
                <span class="slider round"></span>
            </label>
        </div>
    </div>
    </div>
    </div>
    <!--product-->
    <div class="dataContainer">
    </div>
     <!--JS-->
     <script src="buttons.js"></script>
     <script src="valid.js"></script>
     <script src="forminput.js"></script>
     <!--JS-->
</body>
</html>

JS отправка данных с формы и создание елемента

let products = []; // Глобальний масив для зберігання продуктів

function getAndShowAllProducts() {
  let sortedProducts = [...products]; // Копіюємо продукти для сортування
  //alert(products[0].productImage)
  // Сортування за ціною, якщо чекбокс вибраний
  const sortCheckbox = document.getElementById("sortcheckbox");
  if (sortCheckbox.checked) {
    sortedProducts.sort((a, b) => a.productLan - b.productLan);
  }

  const dataContainer = document.querySelector(".dataContainer");
  dataContainer.innerHTML = "";

  sortedProducts.forEach((product) => {
    let productCard = document.createElement("div");
    productCard.classList.add("element");

    productCard.innerHTML = `
      <div class="element-data">
        <img src="${product.productImage}" class="element-img">
        <div class="element-name">${product.productName}</div>
        <p class="element-text">Процесор: <span class="element-volume">${product.productProc}</span></p> 
        <p class="element-text">Кількість слотів для дисків: <span class="element-material">${product.productDisk}</span></p>
        <p class="element-text">Кількість оперативної пам'яті: <span class="element-material">${product.productOp}</span></p> 
        <p class="element-text">Ціна: <span class="element-material">${product.productLan}</span></p>  
      </div>
      <div class="element-footer">
        <button class="edit-button" onclick="modifyModalToEdit('${product._id}', '${product.productName}', '${product.productProc}', '${product.productDisk}', '${product.productOp}', '${product.productLan}', '${product.productImage}', '${product.cloudinaryPublicId}')">Edit</button><span> </span>
        <button class="delete-button" onclick="removeProduct('${product._id}', '${product.cloudinaryPublicId}')">Delete</button>
      </div>
    `;

    dataContainer.appendChild(productCard);
  });
}

// Отримання продуктів з бази даних
async function fetchProductsFromDatabase() {
  await fetch("/products")
  .then(res => res.json())
  .then(data => {
  products = data
  getAndShowAllProducts();
  });
}

// Обробник події натискання на кнопку сортування
function handleSortCheckboxChange() {
  getAndShowAllProducts(); // Відображаємо продукти з оновленим сортуванням
}

// Додавання слухача подій на зміну стану чекбокса
const sortCheckbox = document.getElementById("sortcheckbox");
sortCheckbox.addEventListener("change", handleSortCheckboxChange);

// Виклик функції fetchProductsFromDatabase() для отримання продуктів з бази даних
fetchProductsFromDatabase();

function collectFormData() {
  const productForm = document.forms["productForm"];
  let formData = new FormData(productForm);
  productForm.reset();
  return formData;
}

async function sendData() {
  await fetch('/products', {
    method: 'POST',
    body: collectFormData()
  });
}

async function modalpush() {
  if (valid() && validImg()) {
    await sendData();
    fetchProductsFromDatabase(); // Отримати та відобразити оновлений список продуктів
    Modaleclose();
  }
}

async function removeProduct(_id, cloudinaryPublicId) {
  const deleteParams = {
    _id: _id,
    cloudinaryPublicId: cloudinaryPublicId,
  };

  await fetch(`/products/${_id}`, {
    method: "DELETE",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(deleteParams),
  });

  fetchProductsFromDatabase();
}

function modifyModalToEdit(_id, productName, productProc, productDisk, productOp, productLan, productImage, cloudinaryPublicId) {
  document.getElementById("modalcont").style.display = "block";
  document.getElementById("greybg").style.display = "block";
  document.getElementsByClassName("text-h")[0].innerText = "Edit NAS";
  document.getElementById("submit-btn").innerText = "Update";
  document.getElementById('formImage').setAttribute("src", productImage);
  document.getElementById("js-input-model-edit").value = productName;
  document.getElementById("js-proc-edit").value = productProc;
  document.getElementById("js-disk-edit").value = productDisk;
  document.getElementById("js-op-edit").value = productOp;
  document.getElementById("js-lan-edit").value = productLan;
  document.getElementById("productId").value = _id;
  document.getElementById('oldImagePath').value = productImage;
  document.getElementById("oldCloudinaryPublicId").value = cloudinaryPublicId;
}

// Виклик функції getAndShowAllProducts() після її оголошення
getAndShowAllProducts();

// Обробник події натискання на кнопку пошуку
const searchButton = document.querySelector(".green-button");
searchButton.addEventListener("click", handleSearch);

function handleSearch() {
  const searchField = document.querySelector(".searchfield");
  const searchTerm = searchField.value.trim().toLowerCase();

  if (searchTerm === "") {
    // Якщо поле пошуку порожнє, відображаємо всі продукти
    getAndShowAllProducts();
    return;
  }

  const filteredProducts = products.filter((product) =>
    product.productName.toLowerCase().includes(searchTerm)
  );

  if (filteredProducts.length > 0) {
    // Якщо є знайдені продукти, відображаємо їх
    const dataContainer = document.querySelector(".dataContainer");
    dataContainer.innerHTML = "";

    filteredProducts.forEach((product) => {
      let productCard = document.createElement("div");
      productCard.classList.add("element");

      productCard.innerHTML = `
        <div class="element-data">
          <img src="${product.productImage}" class="element-img">
          <div class="element-name">${product.productName}</div>
          <p class="element-text">Процесор: <span class="element-volume">${product.productProc}</span></p> 
          <p class="element-text">Кількість слотів для дисків: <span class="element-material">${product.productDisk}</span></p>
          <p class="element-text">Кількість оперативної пам'яті: <span class="element-material">${product.productOp}</span></p> 
          <p class="element-text">Ціна: <span class="element-material">${product.productLan}</span></p>  
        </div>
        <div class="element-footer">
          <button class="edit-button" onclick="modifyModalToEdit('${product._id}', '${product.productName}', '${product.productProc}', '${product.productDisk}', '${product.productOp}', '${product.productLan}', '${product.productImage}', '${product.cloudinaryPublicId}')">Edit</button><span> </span>
          <button class="delete-button" onclick="removeProduct('${product._id}', '${product.cloudinaryPublicId}')">Delete</button>
        </div>
      `;

      dataContainer.appendChild(productCard);
    });
  } else {
    // Якщо немає знайдених продуктів, відображаємо повідомлення
    const dataContainer = document.querySelector(".dataContainer");
    dataContainer.innerHTML = "<p>No products found.</p>";
  }
}

Backend на node.js Express

const express = require('express');
const mongoose = require('mongoose');
const router = express.Router();
const Product = require('./back/modelschema');
const bodyParser = require("body-parser");
const cloudinary = require('cloudinary');
const formidable = require('formidable');


const app = express();
const PORT = 3000;

cloudinary.v2.config({
  cloud_name: 'SECRET',
  api_key: 'SECRET',
  api_secret: 'SECRET',
  secure: true,
});

const mongoDB = "SECRET";
mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => {
    console.log("З'єднання з БД встановлено");
  })
  .catch((err) => {
    console.log(err);
  });

app.use(express.static(__dirname + '/public'));

app.listen(PORT, (error) => {
  error ? console.log(error) : console.log(`Сервер запущено на порту ${PORT}`);
});

// Отримання всіх продуктів
app.get("/products", (req, res) => {
  Product.find({})
    .then((products) => {
      return res.send(products);
    })
    .catch((error) => {
      console.log(error);
      res.status(500).send("Помилка при отриманні продуктів");
    });
});

// Видалення продукту
app.delete("/products/:id", (req, res) => {
  const productId = req.params.id;

  Product.findByIdAndRemove(productId)
    .then((product) => {
      if (!product) {
        return res.status(404).send("Продукт не знайдено");
      }

      // Видалення зображення з Cloudinary
      cloudinary.uploader.destroy(product.cloudinaryPublicId, { invalidate: true }, (error, result) => {
        if (error) {
          console.log(error);
        }
      });

      res.send("Продукт успішно видалено");
    })
    .catch((error) => {
      console.log(error);
      res.status(500).send("Помилка при видаленні продукту");
    });
});

router.post("/", (req, res) => {
  const form = formidable({
    multiples: true,
    keepExtensions: true,
  });
  form.parse(req, async (err, fields, files) => {
    if (err) {
      console.log("Error parsing the files");
      return res.status(400).json({
        status: "Fail",
        message: "There was an error parsing the files",
        error: err,
      });
    }

    const { productId, productName, productProc, productDisk, productOp, productLan, oldCloudinaryPublicId, oldImagePath } = fields;
    const { productImage } = files;

    const productInfo = {
      productName,
      productProc,
      productDisk,
      productOp,
      productLan
    };
    console.log(fields, files)
    if (!productImage || !productImage.originalFilename) {
      // Якщо зображення не завантажено або не змінено - додаємо старі поля
      productInfo.productImage = oldImagePath;
      productInfo.cloudinaryPublicId = oldCloudinaryPublicId;
      console.log(productInfo.productImage);
      saveDataToDB(productId, productInfo, res);
    } else {
      // Якщо зображення змінено - завантажуємо нове зображення до Cloudinary
      const getImagePath = productImage.filepath;
      cloudinary.uploader.upload(getImagePath, (err, image) => {
        if (err) {
          console.warn(err);
        }

        productInfo.productImage = image && image.url; // Перевірка, чи існує image і має властивість url
        productInfo.cloudinaryPublicId = image && image.public_id;
        saveDataToDB(productId, productInfo, res);
        cloudinary.uploader.destroy(oldCloudinaryPublicId);
      });
    }
  });
});

router.get("/list", (req, res) => {
  Product.find((err, docs) => {
    if (!err) {
      res.send(docs);
    } else {
      console.warn('Error in retrieving product list:', err);
    }
  });
});

const jsonParser = express.json();
router.delete("/:id", jsonParser, (req, res) => {
  const productId = req.params.id;
  cloudinary.uploader.destroy(req.body.cloudinaryPublicId);
  Product.findByIdAndDelete(productId, (err, docs) => {
    if (err) {
      console.log(err);
    } else {
      res.sendStatus(200);
    }
  });
});

function saveDataToDB(productId, data, res) {
  // Перевіряємо чи створювати новий запис в БД, чи оновлювати наявний
  if (productId == "") {
    // Створюємо новий запис БД
    Product.create(data)
      .then(() => {
        res.sendStatus(200);
      })
      .catch((error) => {
        console.log(error);
        res.status(500).send("Помилка при збереженні продукту");
      });
  } else {
    // Оновлюємо наявний запис БД
    Product.findByIdAndUpdate(productId, data)
      .then(() => {
        res.sendStatus(200);
      })
      .catch((error) => {
        console.log(error);
        res.status(500).send("Помилка при оновленні продукту");
      });
  }
}

app.use("/products", router);

module.exports = router;


Ответы (0 шт):