Отправка на сервер картинок React + Node

Хотел узнать, как можно попробовать загружать с ПК картинку и отправлять ее на какой-нибудь сервис с собственным API, после чего получать оттуда ссылку на картинку и сразу записывать ее в БД. У меня есть код из следующих файлов:

  1. DragDrop.js

    import React from "react"; 
    import './DragDrop.css' 
    import { useTranslation } from 'react-i18next';  
    import axios from "axios";
    const sendDataToServer = async (imageUrl) => {
    try 
        {
        const formData = new FormData();
    
    formData.append("file", imageUrl);
    
    // Отправка данных на сервер
    const response = await axios.post("/api/uploadFile", formData, {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    });
    
    if (response.status === 200) {
      console.log("Фотография успешно загружена");
    } else {
      console.error("Ошибка при загрузке фотографии:", response.statusText);
    }
    } 
    
     catch (error) {
        console.error("Ошибка при загрузке фотографии:", error.message);
      }
    };
    
    // drag drop file component
    function DragDropFile() {
      const {t, i18n} = useTranslation()
        // drag state
        const [dragActive, setDragActive] = React.useState(false);
        // ref
        const inputRef = React.useRef(null);
    
        // handle drag events
        const handleDrag = function(e) {
          e.preventDefault();
          e.stopPropagation();
          if (e.type === 'dragenter' || e.type === 'dragover') {
            setDragActive(true);
          } else if (e.type === 'dragleave') {
            setDragActive(false);
          }
        };
    
        // triggers when file is dropped
        const handleDrop = async function(e) {
          e.preventDefault();
          setDragActive(false);
          if (e.target.files && e.target.files.length > 0) {
            handleFile(e.target.files);
            await sendDataToServer(e.dataTransfer.files[0]);
          }
          else {
            console.error('Нет загруженных файлов');
          }
        };
    
        function handleFile(files) {
          alert("Number of files: " + files.length);
        }
    
        // triggers when file is selected with click
        const handleChange = async function(e) {
          e.preventDefault();
          if (e.target.files && e.target.files.length > 0) {
            console.log("Выбран файл:", e.target.files[0]);
            handleFile(e.target.files);
            await sendDataToServer(e.target.files[0]);
          }
          else {
            console.error('Нет загруженных файлов');
          }
        };
    
    
      // triggers the input when the button is clicked
        const onButtonClick = (e) => {
          e.preventDefault();
          inputRef.current.click();
        };
    
        return (
    
          <form className="element-animation" id="form-file-upload" onDragEnter={handleDrag} onSubmit={(e) => e.preventDefault()}>
            <input ref={inputRef} type="file" id="input-file-upload" multiple={true} onChange={handleChange} />
            <label id="label-file-upload" htmlFor="input-file-upload" className={dragActive ? "drag-active" : "" }>
              <div>
                <p>{t('post.pic')}</p>
                <button className="upload-button" onClick={onButtonClick}>{t('post.picButton')}</button>
              </div> 
            </label>
            { dragActive && <div id="drag-file-element" onDragEnter={(e) => e.preventDefault()} onDragLeave={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()} onDrop={handleDrop}></div> }
          </form>
        );
      };
    
      export default DragDropFile;
    
  2. Form.js

import React, { useState } from "react";

import { useTranslation } from "react-i18next";
import Modal from "./Modal/Modal";  
import { useInput } from "../hooks/use-form-validate";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPersonCircleCheck } from "@fortawesome/free-solid-svg-icons";
import DragDropFile from "./DragNDrop/DragDrop.js";
import axios from "axios";

const sign = <FontAwesomeIcon icon={faPersonCircleCheck} size="2x" marginRight="10px" />;

function Form() {
  const [modalActive, setModalActive] = useState(false);
  const handleSubmit = async (imageUrl) => {
    try {
          const response = await axios.post("/api/addData", {
             imageUrl: imageUrl, // Передаем URL загруженного изображения
             title: title.value,
             link: link.value,
             text: text.value 
});
if (response.status === 200) {
    console.log("Данные успешно отправлены на сервер");
    await sendDataToServer(imageUrl);
    // setModalActive(true); // Показываем модальное окно об успешной отправке
  } else {
    console.error("Ошибка при отправке данных на сервер:", response.statusText);
  }
} catch (error) {
  console.error("Ошибка при отправке данных на сервер:", error.message);
}
 };

const sendDataToServer = async (imageFile) => {
try {
  const formData = new FormData();
  formData.append("file", imageFile);

  // Отправка изображения на сервер
  const response = await axios.post("/api/uploadFile", formData, {
    headers: {
      "Content-Type": "multipart/form-data",
    },
  });

  if (response.status === 200) {
    console.log("Фотография успешно загружена");
    // Вызываем handleSubmit после успешной загрузки изображения
    handleSubmit(response.data.imageUrl); 
  } else {
    console.error("Ошибка при загрузке фотографии:", response.statusText);
  }
} catch (error) {
  console.error("Ошибка при загрузке фотографии:", error.message);
}


};

//   const handleFilesDrop  = async (files) => {
//     try {
//         const formData = new FormData();
//         formData.append("file", files[0]);

//         const response = await axios.post("/api/uploadPhoto", formData, {
//             headers: {
//                 "Content-Type": "multipart/form-data"
//             }
//         });
//         console.log("Ответ сервера:", response);

//         if (response.status === 200) {
//             console.log("Фотография успешно загружена");
//             
//         } else {
//             console.error("Ошибка при загрузке фотографии:", response.statusText);
//         }
//     } catch (error) {
//         console.error("Ошибка при загрузке фотографии:", error.message);
//     }
// };



// Форма валидации
  const { t } = useTranslation();
  const title = useInput("", { isEmpty: true, minLength: 5 });
  const link = useInput("", { isEmpty: true, minLength: 2 });
  const pic = useInput("", { isEmpty: true, minLength: 1 });
  const text = useInput("", { isEmpty: true, minLength: 2 });

  return (
     <form className="contact__form" onSubmit={handleSubmit}>
       <div className="input__data">
         <input
           onBlur={title.onBlur}
           value={title.value}
           onChange={title.onChange}
           className="name__input input form__control element-animation"
           type="text"
           placeholder={t("post.title")}
           name="title"
           required
         />
         {title.isDirty && title.isEmpty && <div className="form__error">{t("error.empty")}</div>}
         {title.isDirty && title.minLengthError && (
           <div className="form__error">{t("error.length")}</div>
         )}
       </div>

  <div className="input__data">
    <input
      onBlur={link.onBlur}
      value={link.value}
      onChange={link.onChange}
      className="link__input input form__control element-animation"
      type="text"
      placeholder={t("post.link")}
      name="link"
      required
    />
    {link.isDirty && link.isEmpty && <div className="form__error">{t("error.empty")}</div>}
    {link.isDirty && link.minLengthError && (
      <div className="form__error">{t("error.length")}</div>
    )}
  </div>

  <DragDropFile sendDataToServer={sendDataToServer}/>

  <div className="input__data">
    <textarea
      onBlur={text.onBlur}
      value={text.value}
      onChange={text.onChange}
      className="form__textarea form__control element-animation"
      name="text"
      id="text"
      placeholder={t("post.text")}
    ></textarea>
    {text.isDirty && text.isEmpty && <div className="form__error">{t("error.empty")}</div>}
    {text.isDirty && text.minLengthError && (
      <div className="form__error">{t("error.length")}</div>
    )}
  </div>

  <button
    disabled={!title.inputValid || !link.inputValid || !text.inputValid}
    className="form__btn form__control element-animation"
    type="submit"
    name="submit"
  >
    {t("post.button")}
  </button>
  <Modal active={modalActive} setActive={setModalActive}>
    {sign}
    <p>{t("contact.modalThanks")}</p>
    <br />
    <p>{t("contact.modalRequest")}</p>
  </Modal>
</form>
  );
  }

  export default Form;
  1. server.js

      // Импортируем необходимые зависимости
      const express = require('express');
      const bodyParser = require('body-parser');
      const mysql = require('mysql');
      const cors = require('cors');
      //const cloudinary = require('cloudinary').v2;
      const multer = require('multer');
      import {
      v2 as cloudinary
      } from 'cloudinary';
    
      cloudinary.config({
          cloud_name: 'droi2nd1z',
          api_key: '598973367993171',
          api_secret: '***************************'
      });
      const connection = mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '************',
          database: 'wtf_db'
      });
    
      const upload = multer({
        dest: 'uploads/'
      });
      connection.connect((err) => {
         if (err) {
             console.error('Ошибка подключения к базе данных:', err);
             throw err;
      }
      console.log('Подключение к базе данных успешно установлено');
      });
    
      // Создаем экземпляр express
      const app = express();
    
      // Используем middleware для обработки JSON данных
      app.use(bodyParser.json());
      app.use(cors());
      // Определяем маршрут для обработки POST запросов
      // app.post("/api/addData", upload.single('file'), async (req, res) => {
    
      //   // Получаем данные из тела запроса
      //   const { title, link, pic, text } = req.body;
    
      //   // Выполняем операции с базой данных 
      //   const sql = `INSERT INTO past_orders_info (Header, link, photo, description) VALUES (?, ?, ?, ?)`;
      //   connection.query(sql, [title, link, pic, text], (err, result) => {
      //     if (err) {
      //       console.error('Ошибка выполнения SQL запроса:', err);
      //       res.status(500).send('Ошибка сервера');
      //       return;
      //     }
      //     console.log('Данные успешно добавлены в базу данных');
      //     res.status(200).send('Данные успешно добавлены в базу данных');
      //   });
      // });
    
      // app.post("/api/uploadFile", upload.single('file'), async (req, res) => {
      //   if (!req.files || Object.keys(req.files).length === 0) {
      //     return res.status(400).send('Нет загруженных файлов.');
      //   }
    
      //const file = req.files.file;
      try {
           const result = await cloudinary.uploader.upload(req.file.path);
           console.log('File uploaded to Cloudinary:', result);
           res.status(200).send(result.secure_url);
      } catch (error) {
            console.error('Error uploading file to Cloudinary:', error);
            res.status(500).send('Internal server error');
      }
      // cloudinary.uploader.upload(file.tempFilePath, (error, result) => {
      //   if (error) {
      //     console.error('Ошибка при загрузке фотографии в Cloudinary:', error);
      //     return res.status(500).send('Ошибка сервера');
      //   }
    
      console.log('Фотография успешно загружена в Cloudinary:', result);
    
      const imageUrl = result.secure_url;
         res.status(200).send(imageUrl);
      // });
    
    
      // Устанавливаем порт, на котором будет работать сервер
      const port = process.env.PORT || 3000;
    
      // Запускаем сервер на выбранном порту
      app.listen(port, () => {
          console.log(`Сервер запущен на порту ${port}`);
      });
    

Как видно из кода, я пытался сделать что-то дельное с облачным сервисом cloudinary, который вряд ли даст что-то с ним сделать, хоть я и смог авторизоваться через GH-аккаунт с помощью VPN. Хочется понять, в правильном ли я вообще направлении иду и пользовался ли кто-нибудь эти облачным сервисом в последнее время? Какие есть аналоги подобного сервиса со своими API? Если будут какие-либо советы по правке кода и возможному решению моей задачи - буду безумно признателен!! Заранее извиняюсь за корявую табуляцию в коде...


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