see the screenshot . Why images getting corrupted? I am trying to upload images using axois post but axois post can’t processing my images correctly . My code divided in two part. First part where I writing logic for upload multi image and second part I am using it in my page component.
first part
this code for upload multi image
export const MultiImageUpload = ({Setimage}) => { const [selectedImages, setSelectedImages] = useState([]); const onSelectFile = (event) => { const selectedFiles = event.target.files; const selectedFilesArray = Array.from(selectedFiles); const imagesArray = selectedFilesArray.map((file) => { return URL.createObjectURL(file); }); setSelectedImages((previousImages) => previousImages.concat(imagesArray)); Setimage((previousImages) => previousImages.concat(imagesArray)); // FOR BUG IN CHROME event.target.value = ""; }; function deleteHandler(image) { setSelectedImages(selectedImages.filter((e) => e !== image)); Setimage(selectedImages.filter((e) => e !== image)); URL.revokeObjectURL(image); }
second part now I am importing this component in my page
const AdsPost = ({data}) => { const[image,Setimage] = useState([]) var data = new FormData(); image.forEach(file=>{ data.append("files", file) console.log("image_url:",file) }) let submit_ads = axios.post(url,data,{headers:headers}).then((res)=>{ console.log(res) })
here is myjsx
<MultiImageUpload Setimage={Setimage}/>
I can upload image using postman but don’t know why axois post can’t upload images.
Advertisement
Answer
Here is your problem :
image.forEach(file=>{ data.append("files", file) console.log("image_url:",file) })
The parameter file
is not a file, but it’s the result of
const imagesArray = selectedFilesArray.map((file) => { return URL.createObjectURL(file); // <--- this line });
In other words, you are essentially doing
data.append("files", URL.createObjectURL(file));
Fix that and your code should work.
Solution
Here is a sandbox with a proposed solution, the idea is to delegate the state of the files to a Provider, and use the context down in child components as needed.
./context/files.js
import { createContext } from "react"; export default createContext({ /** @return {{ file:File, dataUrl:string }[]]} */ get files() { return []; }, /** @return {Error[]} */ get errors() { return []; }, /** @param {File[]} files */ addFiles(files) {}, /** @param {File} file */ removeFile(file) {}, /** @param {Error[]} errors */ setErrors(errors) {} });
./providers/FilesProvider.jsx
import { useContext, useMemo, useState } from "react"; import FilesContext from "../context/files"; const FilesProvider = ({ children }) => { const [internal, setInternal] = useState(() => ({ files: [], errors: [] })); const contextValue = useMemo( () => ({ get files() { return internal.files; }, get errors() { return internal.errors; }, addFiles(filesAdded) { setInternal(({ files, errors }) => ({ files: files.concat( filesAdded.map((file) => ({ file, dataUrl: URL.createObjectURL(file) })) ), errors })); }, removeFile(fileRemoved) { URL.revokeObjectURL(fileRemoved); setInternal(({ files, errors }) => ({ files: files.filter(({ file }) => file !== fileRemoved), errors })); }, setErrors(errors) { setInternal(({ files }) => ({ files, errors })); } }), [internal] ); return ( <FilesContext.Provider value={contextValue}> {children} </FilesContext.Provider> ); }; const useFiles = () => useContext(FilesContext); export default FilesProvider; export { useFiles };
Usage
<FilesProvider> <FilesSelectComponent /> </FilesProvider>
and
const { files, errors, addFiles, removeFile, setErrors } = useFiles();