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();