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.
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]
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.
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
.
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.
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);
}
});
LE : am citit rapid pe diagonala postarile din thread asa ca nu stiu daca o sa te ajute neaparat ce ti-am trimis aici