Skip to content
Advertisement

Why my images converted to string when submitting post request?

see the screenshot enter image description here . 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();
User contributions licensed under: CC BY-SA
11 People found this is helpful
Advertisement