How to upload multiple files with fields at once with FormData?

129 Views Asked by At

I have a pocketbase collection with name, image and order fields. I am trying to upload all the images with a unique name and images using FormData in parallel.

Here's is my code:

export default function AddPhotosAdmin({ photosDb }: PhotoDisplayProps) {

    async function addPhotos(formData: FormData) {
        'use server'

        const name = formData.get("name") as string
        let order = 0
        const dataPost = new FormData
        const Image_array = Array.from(formData.getAll("Image"))
        Image_array.map((image) => {
            dataPost.append('name', name)
            dataPost.append('Image', image)
            dataPost.append('order', (order++).toString())
        })
        
        const pb = new PocketBase(process.env.DB_ADDR);
        pb.collection('Photos').create(dataPost);
        revalidatePath("/Photos")
    }
    
    return (
        <div>
            <form action={addPhotos} className="text-black">

                <input name="name" />

                <input
                    type="file"
                    name="Image"
                    required
                    multiple
                    accept="image/*"
                    className="text-white"
                ></input>

                <input type="submit" className="text-white" value="Créer" />
            </form>
        </div>
    )

I have tried a lot of ways to try and send all the data at once and to no success. Using a loop, POST is auto cancelled and appears not the most suitable choice.

1

There are 1 best solutions below

1
serohrt On BEST ANSWER

I suggest using Promise.all() to handle multiple asynchronous operations concurrently. Array.map() does not ensure that each upload completes before moving to the next one. i edited the code so it uses Promise, hope this helps you.

interface PhotoDisplayProps {
  photosDb: any; 
}
export default function AddPhotosAdmin({ photosDb }: PhotoDisplayProps) {
  async function addPhotos(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    const name = formData.get("name") as string;
    const pb = new PocketBase(process.env.DB_ADDR);
    const imageFiles = formData.getAll("Image");
    const dataPromises = Array.from(imageFiles).map(async (imageFile, index) => {
      const order = index; 
      const dataPost = new FormData();
      dataPost.append("name", name);
      dataPost.append("Image", imageFile);
      dataPost.append("order", order.toString());
      await pb.collection("Photos").create(dataPost);
    });

    try {

      await Promise.all(dataPromises);
      revalidatePath("/Photos");
    } catch (error) {
      console.error("Error uploading photos:", error);
    }
  }

  return (
    <div>
      <form onSubmit={addPhotos} className="text-black">
        <input name="name" />
        <input
          type="file"
          name="Image"
          required
          multiple
          accept="image/*"
          className="text-white"
        ></input>
        <input type="submit" className="text-white" value="Créer" />
      </form>
    </div>
  );
}