Загрузка карточки товара с двумя картинками REACT ,Api [как загрузить файл ajax-ом на сервер]

Доброго времени суток ! Начал делать Web-приложение и столкнулся с проблемой , не могу загрузить карточку товара с картинкой на сервер хотя через постман все работает,

import React, { useState } from “react”;
import ‘…/…/settingsDiscount/settingsDiscount’
import settingLogo from ‘…/…/img/setting.svg’
import addPictures from ‘…/…/img/add-pictyres.svg’
import plusAdd from ‘…/…/img/plusAdd.svg’

function DiscountAdd(props) {
const [name, setName] = useState(‘’);
const [image, setImage] = useState(null);
const [description, setDescription] = useState(‘’);
const [promocode, setPromocode] = useState(‘’);
const [link, setLink] = useState(‘’);
const [barcode, setBarcode] = useState(‘’);
const [date, setDate] = useState(null);
const [category, setCategory] = useState(‘’)

function handleSubmit(e) {
    e.preventDefault();
   props.handleAddDiscount(name, image, description, promocode, link, barcode, date, props.categoryID);

}

function handleName(e) {

    setName(e.target.value)
}

function handleImage(e) {
    
    setImage(e.target.files[0])
}

function handleDescription(e) {

    setDescription(e.target.value);
}

function handlePromocode(e) {

    setPromocode(e.target.value);
}


function handleLink(e) {

    setLink(e.target.value);
}

function handleBarcode(e) {

    setBarcode(e.target.files[0]);
}

function handleData(e) {

    setDate(e.target.value);
}



return (
    <div className="settings">
        <form className="setting" onSubmit={handleSubmit}>
            <div className="setting__logo">
                <img src={settingLogo} />
                <p className="setting__text">НАСТРОЙКИ</p>
            </div>
            <input
                className="setting__name-discount"
                type="text"
                placeholder="Название скидки"
                onChange={handleName}
            />
            <div className="input__file">
                <input type="file"
                    onChange={handleImage}
                    className="input__file-add"
                    placeholder="Добавить картинку"
                    name="add-file"
                    accept="uploads/*"
                    id="add-file" />
                <img className="input-file-img" src={addPictures} />
                <label for="add-file" className="input__file-label">Добавить картинку</label>
            </div>
            <textarea
                className="input__text"
                id="add-text"
                name="add-text"
                placeholder="Описание данного сервиса..."
                onChange={handleDescription}></textarea>
            <p className="input__add-text" for='add-text'>Описание промокода</p>
            <div className="input__promocode">
                <input type="text"
                    placeholder="Промокод"
                    className="input__add-promocode"
                    onChange={handlePromocode}
                />
                <input type="text"
                    className="input__add-date"
                    placeholder="До __ __ ______г."
                    onChange={handleData}
                />
            </div>
            <button className="input__button-promocode" for='add-text'>Добавить промокод</button>
            <input
                type="text"
                className="input__add-link"
                placeholder="Добавить ссылку"
                onChange={handleLink}
            />
            <div className="input__barcode">
                <input
                    type="file"
                    className="input__barcode-add"
                    placeholder="Добавить штрихкоде"
                    name="add-barcode"
                    accept="uploads/*"
                    id="add-barcode"
                    onChange={handleBarcode}
                />
                <img className="input-barcode-img" src={plusAdd} />
                <label for="add-barcode" className="input__file-barcode">Добавить штрихкод</label>
            </div>
            <div className="setting__buttons setting__buttons_add-discount">
                <button className="setting__button">СОХРАНИТЬ</button>
            </div>
        </form>
    </div>
);

}

export default DiscountAdd;

Как выглядит запрос в браузере в окошке Network? Очень похоже что браузер не разрешает кроссдоменные аякс запросы. Ключевое слово которое гуглить для понимания проблемы - CORS.

Вот как ИИ описывает CORS:

CORS (Cross-Origin Resource Sharing) - это механизм, который позволяет веб-страницам получать доступ к ресурсам (таким как данные API) на других доменах, отличных от их собственного. Он используется для решения проблемы безопасности, возникающей при попытке выполнить запрос на другой домен.
Без использования CORS, веб-страницы могут быть ограничены в своей способности получать данные с других доменов из соображений безопасности браузера. CORS определяет и применяет набор заголовков HTTP для разрешения или запрета доступа к ресурсам на других доменах.
CORS задает правила и ограничения для запросов между различными источниками (origin) - домен, протокол и порт. Если сервер, на который делается запрос, разрешает доступ с определенного источника, то происходит успешное выполнение запроса, иначе возникает ошибка.
CORS используется для защиты серверных ресурсов от несанкционированного доступа, предотвращения CSRF (межсайтовой подделки запросов) и обеспечения безопасности веб-приложений.


console.log(name, image, description, promocode, link, barcode, date, category)

Я имел в виду эту вкладку:


Ошибка 500 это результат попытки загрузить файлы. 500 ошибка означает что сервер “упал” с ошибкой когда обрабатывал запрос. Причина может быть в чем угодно: нехватка параметров, невалидные параметры, невалидный метод (типа ожидался post а ты делаел get), отсутствие авторизации.

Не вдаваясь глубоко в код похоже что решение не сратается из-за формата отправляемых данных. body должен быть объектом этого типа: FormData - Web APIs | MDN когда Content-Type: "multipart/form-data".

И чтобы дважды не вставать. Тебе нужно будет использовать file API для того чтобы корректно считать бинарный файл.

Сам я не раз сталкивался с решением этой задачи, актуальность списка АПИ подтверждаю своим опытом.

Вот что ИИ чатбот накидал как пример. Тут затронуты все ключевые АПИ которые тебе нужно использовать. Архитектурно, конечно, код не для продакшена.


To send an uploaded image file to the backend using JavaScript, you can follow these steps:

  1. Create an HTML form with an input field of type ‘file’ to allow users to select an image file.
<form id="imageForm">
  <input type="file" id="imageInput">
  <button type="submit">Upload</button>
</form>
  1. Add an event listener to the form submission to prevent the default behavior and handle the file upload.
document.getElementById('imageForm').addEventListener('submit', function(e) {
  e.preventDefault(); // prevent form submission
  uploadImage();
});
  1. Implement the uploadImage function to handle the file upload. You can use the Fetch API or XMLHttpRequest to POST the image file to the backend.

Using Fetch API:

function uploadImage() {
  const imageInput = document.getElementById('imageInput');
  const file = imageInput.files[0];

  const formData = new FormData();
  formData.append('image', file);

  fetch('/backend-url', {
    method: 'POST',
    body: formData
  })
  .then(response => response.json())
  .then(data => {
    // Handle response from the backend
    console.log(data);
  })
  .catch(error => {
    // Handle error
    console.error(error);
  });
}

Using XMLHttpRequest:

function uploadImage() {
  const imageInput = document.getElementById('imageInput');
  const file = imageInput.files[0];

  const xhr = new XMLHttpRequest();
  const formData = new FormData();

  formData.append('image', file);
  xhr.open('POST', '/backend-url', true);

  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      // Handle response from the backend
      const response = JSON.parse(xhr.responseText);
      console.log(response);
    }
  };

  xhr.send(formData);
}

Replace /backend-url with the actual URL where your backend API endpoint is expecting the image file. Note that the backend should have appropriate handling to store or process the uploaded image file.


Спасибо!