Problema la incarcarea mai multor imagini intr-un obiect FormData in React

Doresc sa trimit datele dintr-un formular prin intermediul unui obiect FormData din React in Node.js.Problema este ca se trimite o singura imagine din multitudinea de imagini selectate, mai precis ultima imagine selectata.


2022-06-18_202813

2 Likes

pai in prima imagine in for, tu suprascrii formData.images tot timpul cu files[i], de-asta ti-l ia pe ultimul mereu. Images ar trebui sa fie array (cred) si sa faci push in el files[i]

4 Likes

formData.images = [...formData.files] sau direct images = files in loc de for-ul acela.

Poti utiliza formData = {...formData, subcategory_id, name, description, article_code, outer_material si restul } ca sa declari formData mai elegant daca nu schimbi nimic. In request in axios vad ca faci destructuring la payload cand ar fi destul sa scoti {} dintre …formData.

1 Like

Multumesc pentru raspunsuri! Am incercat for (let i = 0; i < files.length; i++) { formData.append("images[]", files[i]) } dar vad ca nu merge, pe Node.js imi vede ca array gol.Am incercat si asa: formData.images = []; for (let i = 0; i < files.length; i++) { formData.images.push(files[i]) } de data asta am o eroare:


Incercai si asa: formData.images = files si rezultatul e tot un array gol.Iar asa:formData.images = [...formData.files] nu o sa mearga pentru ca files e de fapt variabila din hook-ul useState: const [files, setFiles] = useState([])

Eu am folosit ceva de genul recent, am un proiect prin care trebuie sa trimit serverului mai multe fisiere selectate pe partea de interfata.

var formData = new FormData();
var selectedFiles = document.getElementById('upload-input');
for (var i = 0; i < selectedFiles.files.length; i++)
    formData.append('files', selectedFiles.files[i]);

Pe partea de server eu am Java, dar la tine probabil fisierele ar trebui sa fie in req.files.

1 Like

Pune codul ca si text. Este mai usor de citit si reprodus.

Nu stiu React, dar sigur iti suprascrii array-ul.

s-ar putea ca fix la append sa aibe problema (tin minte ca mi-am batut si eu capul cu asta intr-un proiect), trebuie sa dai nume fiecarei imagini in parte:
formData.append('file' + i, selectedFiles.files[i]);

Probabil depinde si limbajul de pe backend, la mine problemele erau cu C#

*Am gasit acum proiectul, incearca sa trimiti datele si fara sa setezi headers (acel config), poate e ceva in neregula cu el.

Altceva, in nodejs, vezi ca acel upload.array("images") si req.files sa nu trebuiasca sa aibe acelasi nume, adica upload.array("files"), si la fel setat si in storage.

Aici exemplu, foloseste aceeasi lib multer ca si tine.

3 Likes

Aici este codul:

import express from "express";
import {
    updateProduct,
    deleteProduct,
    getProductItem,
    getProductItems,
    getProductsFilterActiveSubmenu,
    getProductsFilterPrice,
    getMinMaxfilterPrice,
} from "../controllers/products.js";
import multer from "multer";
import Product from "../models/Product.js";

const router = express.Router();
router.get("/filter/:activeSubmenu", getProductsFilterActiveSubmenu);
router.get("/filter/minmax/:activeSubmenu", getMinMaxfilterPrice);
router.get("/filter/:activeSubmenu/:min/:max", getProductsFilterPrice);
router.put("/:id", updateProduct);

router.delete("/:id", deleteProduct);

router.get("/:id", getProductItem);
router.get("/subcategory/:id", getProductItems);

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "images");
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname);
    },
});

const upload = multer({ storage: storage });

router.post("/create", upload.array("images"), async function (req, res, next) {

    req.body.images = [];

    for (var i = 0; i < req.files.length; i++) {
        req.body.images.push(req.files[i].filename);
    }

    const newProduct = new Product(req.body);
    try {
        const savedProduct = await newProduct.save();
        res.status(200).json(savedProduct);
    } catch (err) {
        next(err);
    }
});
export default router;
import React from "react";
import { useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

function Admin() {
  const mystyle = {
    color: "white",
    backgroundColor: "DodgerBlue",
    padding: "10px",
    fontFamily: "Arial",
  };
  const ulStyle = {
    listStyle: "none",
    flexDirection: "column",
  };
  const panelstyle = {
    color: "white",
    backgroundColor: "grey",
    padding: "10px",
    fontFamily: "Arial",
  };

  const [adaugaIsActive, setDdaugaIsActive] = useState(false);

  const [subcategory_id, setSubcategoryId] = useState(0);
  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [article_code, setArticleCode] = useState("");

  const [outer_material, setOuterMaterial] = useState("");
  const [inner_material, setInnerMaterial] = useState("");
  const [gender, setGender] = useState("");
  const [season, setSeason] = useState("");
  const [price, setPrice] = useState(0);

  const [files, setFiles] = useState([]);
  const uploadImages = (e) => {
    setFiles(e.target.files);
  };

  const submitForm = async (e) => {
    e.preventDefault();

    const formData = new FormData();

    formData.subcategory_id = subcategory_id;
    formData.name = name;
    formData.description = description;
    formData.article_code = article_code;
    formData.outer_material = outer_material;
    formData.inner_material = inner_material;
    formData.gender = gender;
    formData.season = season;
    formData.price = price;
    // formData.images = [];

    // Object.values(files).forEach((file) => {
    //   formData.images = file;
    // });
    formData.images = files;

    // for (let i = 0; i < files.length; i++) {
    //   formData.images.push(files[i]);
    // }
    // for (let i = 0; i < files.length; i++) {
    //   formData.append("images", files[i]);
    // };
    try {
      const config = {
        headers: {
          "Content-Type": "multipart/form-data",
          "Access-Control-Allow-Origin": "*",
        },
      };

      const { data } = await axios.post(
        "http://localhost:8800/api/products/create",
        {
          ...formData,
        },
        config
      );
      console.log(data);
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <div className="container-fluid">
      <div className="row justify-content-center">
        <div className="col-2">
          <div className="sidebar vh-100" style={mystyle}>
            <ul className="d-flex justify-content-center" style={ulStyle}>
              <li>
                <Link to="" onClick={() => setDdaugaIsActive(true)}>
                  Adauga produs
                </Link>
              </li>
              <li>
                <Link to="">Editeaza produs</Link>
              </li>
            </ul>
          </div>
        </div>
        <div className="col-8" style={panelstyle}>
          {adaugaIsActive && (
            <div className="container px-5 my-5">
              <div className="row justify-content-center">
                <div className="col-lg-8">
                  <div className="card border-0 rounded-3 shadow-lg">
                    <div className="card-body p-4">
                      <div className="text-center">
                        <p className="mb-4 text-muted">Adauga produs</p>
                      </div>

                      <form id="contactForm" onSubmit={(e) => submitForm(e)}>
                        <div className="row">
                          <div className="col-6">
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="subcategory_id"
                                type="text"
                                placeholder="Id-ul subcategoriei"
                                value={subcategory_id}
                                onChange={(e) =>
                                  setSubcategoryId(e.target.value)
                                }
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="name"
                                type="text"
                                placeholder="Nume"
                                value={name}
                                onChange={(e) => setName(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="description"
                                type="text"
                                placeholder="Descriere"
                                value={description}
                                onChange={(e) => setDescription(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="article_code"
                                type="text"
                                placeholder="Cod articol"
                                value={article_code}
                                onChange={(e) => setArticleCode(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="outer_material"
                                type="text"
                                placeholder="Material exterior"
                                value={outer_material}
                                onChange={(e) =>
                                  setOuterMaterial(e.target.value)
                                }
                              />
                            </div>
                          </div>
                          <div className="col-6">
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="inner_material"
                                type="text"
                                placeholder="Material interior"
                                value={inner_material}
                                onChange={(e) =>
                                  setInnerMaterial(e.target.value)
                                }
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="gender"
                                type="text"
                                placeholder="Gen"
                                value={gender}
                                onChange={(e) => setGender(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="season"
                                type="text"
                                placeholder="Sezon"
                                value={season}
                                onChange={(e) => setSeason(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                className="form-control"
                                id="price"
                                type="text"
                                placeholder="Pret"
                                value={price}
                                onChange={(e) => setPrice(e.target.value)}
                              />
                            </div>
                            <div className=" d-flex mt-4">
                              <input
                                type="file"
                                id="file"
                                name="images"
                                multiple
                                onChange={uploadImages}
                              />
                            </div>
                          </div>
                          <div className="d-grid">
                            <button
                              className="btn btn-primary btn-lg mt-5"
                              id="submitButton"
                              type="submit"
                            >
                              Submit
                            </button>
                          </div>
                        </div>
                      </form>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export default Admin;

Am avut de facut asta ieri in Angular
nu stiu cum e backendul la tine dar din frontend am trimis asa:

this.screenshots.forEach((screenshot, index) => {
    if (screenshot.file_uuid) {
      formData.append(`file[${index}][uuid]`, screenshot.file_uuid);
    } else {
      formData.append(`file[${index}][image]`, screenshot.original_image);
    }
});

Screenshot from 2022-06-21 15-40-03

LE : am citit rapid pe diagonala postarile din thread asa ca nu stiu daca o sa te ajute neaparat ce ti-am trimis aici

1 Like