Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

joneyspark's avatar

How to Upload Array of files in Vue.js and Laravel ?

Vue file

<template>
  <form @submit.prevent="handleSubmit">
    <label>Course Module PDF</label>
    <input type="file" class="form-control-file" @change="onChangeFiles" />
  </form>
</template>

<script>
export default {
  data() {
    return {
      files: [],
    };
  },
  methods: {
    handleSubmit() {
      let data = new FormData();
      data.append("files[]", this.files);
    },
    onChangeFiles(event) {
      let file = event.target.files[0];
      this.files.push(file);
    },
  },
};
</script>

controller code

$files = $request->files;

  if (count($files) > 0) {

      foreach ($files as $file) {
          $ext = $file->getClientOriginalExtension();
          $name = time().'-'.".".$ext;
          $upload_path = 'backend/files/';
          $upload_url = $upload_path.$name;
          $file->move(public_path($upload_path),$upload_url);
      }

  }

  return "Success";

Nothing is happening

template screenshot:

http://prntscr.com/111fd8j

0 likes
20 replies
liandhas's avatar

Use for loop to push multiple images in an array, then append in files[]

onChangeFiles(event) {
    let file = event.target.files;
	
	for(let i = 0; i<file.length; i++)
	{
		this.files.push(file[i]);
    }
}
neilstee's avatar

@joneyspark I don't see any request on handleSubmit() function.

Add ajax request using axios for it to work.

joneyspark's avatar
handleSubmit() {
      let data = new FormData();
      data.append("files[]", this.files);

      axios.post(data, "/add-course")
        .then(() => {
          this.isLoading = false;
          console.log('Success');
        })
        .catch(error => {
          console.log(error);
          
          
        }
    },
neilstee's avatar

@joneyspark I think you need to add

handleSubmit() {
      let data = new FormData();
      data.append("files[]", this.files);

      axios.post("/add-course", data, {
    headers: {
        'Content-Type': 'multipart/form-data'
    }
  })
        .then(() => {
          this.isLoading = false;
          console.log('Success');
        })
        .catch(error => {
          console.log(error);
          
          
        }
    },
neilstee's avatar

Or this instead, I changed also your html:

<template>
  <form @submit.prevent="handleSubmit">
    <label>Course Module PDF</label>
    <input type="file" class="form-control-file" ref="files" multiple @change="onChangeFiles" />
  </form>
</template>

<script>
export default {
  data() {
    return {
      files: '',
    };
  },
  methods: {
    handleSubmit() {
		let formData = new FormData();
		for( var i = 0; i < this.files.length; i++ ){
          let file = this.files[i];

          formData.append('files[' + i + ']', file);
        }

		axios.post( '/add-course',
          formData,
          {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
          }
        ).then(() => {
          this.isLoading = false;
          console.log('Success');
        })
        .catch(error => {
          console.log(error);
        }
    },
    onChangeFiles(event) {
      this.files = this.$refs.files.files;
    },
  },
};
</script>

I haven't tested this but you should get an idea.

joneyspark's avatar

@neilstee I appreciate your code no doubt but my HTML is a bit different the file selection section has been created using add or remove button so is it possible to keep the same design? and I actually get file data in the console but in Laravel code It does not respond to me

http://prntscr.com/111idic

neilstee's avatar

@joneyspark Oh I thought you can't see the files in the console as well?

Anyways can you show the full request that is sent on the Laravel? Maybe dd($request) ?

Also, are you sure you added the multipart/form-data on your ajax request as I did on my previous replies?

joneyspark's avatar

Can you explain more what data you expect? because I gave the response data screenshot

neilstee's avatar

@joneyspark in your Laravel Controller, use dd($request) to see what payload you are actually receiving.

joneyspark's avatar

@neilstee this code need to change a little bit

  <form @submit.prevent="handleSubmit">
    <label>Course Module PDF</label>
    <input type="file" class="form-control-file" ref="files" multiple @change="onChangeFiles" />
  </form>
</template>

<script>
export default {
  data() {
    return {
      files: [],
    };
  },
  methods: {
    handleSubmit() {
		let formData = new FormData();

		 var self = this;
     	 for (let i = 0; i < this.files.length; i++) {
        	let file = self.files[i];
        	formData.append("files[" + i + "]", file);
      	}

		axios.post( '/add-course',
          formData,
          {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
          }
        ).then(() => {
          this.isLoading = false;
          console.log('Success');
        })
        .catch(error => {
          console.log(error);
        }
    },
    onChangeFiles(event) {
        for (let i = 0; i < this.$refs.files.files.length; i++) {
        this.files.push(this.$refs.files.files[i]);

        console.log(this.files);
      }
    },
  },
};
</script>

Backend Code

//Multiple files

        if ($request->hasFile('files')) {

            foreach ($request->file('files') as $file) {
                $ext = $file->getClientOriginalExtension();
                $name = time().'-'.".".$ext;
                $upload_path = 'backend/files/';
                $upload_url = $upload_path.$name;
                $file->move(public_path($upload_path),$upload_url);

			//save database

                CourseAdditionalFile::create([
                    'course_id' => $course->id,
                    'course_additional_files' => $upload_url
                ]);
            }
        }
1 like
CookieMonster's avatar

Your issue is most like at the handleSubmit() method when you try to use data.append(......).

In your controller, die and dump the values to see if you're getting the intended data.

neilstee's avatar

@joneyspark if you can give us the dd($request) that I've been asking several times already then we can help you solve this faster.

1 like
joneyspark's avatar

Hi,

dd($request) not working on API response but I can return $request->all(); and last time I send you the screenshot of which data I actually get. please check below the screenshot

http://prntscr.com/111nnr0

NEXECHO's avatar

my do this something like in vue

<template>
<div v-if="images.length" class="grid grid-cols-5 gap-4 bg-gray-200 border border-gray-300 rounded-sm p-4">
    <div v-for="image in images" :key="image.id" class="col-span-1">
        <div class="flex flex-col items-center justify-between p-2 bg-white border rounded">
            <img class="h-64" :ref="setItemRef">
            <p class="text-capitalize mt-3">{{ image.name }}</p>
            <p class="text-capitalize mt-3">{{ image.size }}</p>
            <button class="bg-red-400 text-white px-2 py-1 mt-3" :data-index="image.id" v-on:click="deleteImage">Delete</button>
        </div>
    </div>
</div>
<div v-if="!images.length" class="col-span-1 bg-gray-200 border border-gray-300 rounded-sm p-10">
    <p class="text-3xl font-semibold text-center">Upload Photo</p>
    <p class="text-center uppercase text-red-500 mt-5 pt-5 border-t border-red-400">Maximum uploadable photo size is 16 MB</p>
</div>
<hr/>
<div class="grid grid-cols-1 gap-4">
    <input type="file" ref="picker" multiple v-on:change="renderImages" accept="image/*">
    <v-button v-on:click="upload">Submit</v-button>
</div>
</template>
<script>
import UniqueID from '@/features/unique-id';
import formatBytes from '@/features/format-bytes';
export default {
    data() {
        return {
            images: [],
            imageRefs: [],
        }
    },
    methods: {
        setItemRef(el) {
            if (el) {
                this.imageRefs.push(el);
            }
        },
        beforeUpdate() {
            this.imageRefs = [];
        },
        deleteImage(event) {
            const index = event.target.getAttribute('data-index');
            const pos = this.images.findIndex((el) => el.id == index);
            if (pos >= 0) {
                this.images.splice(pos, 1);
            }
        },
        upload() {
            let formData = new FormData();
            for(let i =0; i< this.images.length; i++) {
                formData.append(`photos[]`, this.images[i].file);
            }
            axios({
                method: 'POST',
                url: `${app.uri}/upload`,
                data: formData,
                headers: {
                    'content-type': 'multipart/form-data',
                    'Accept': 'application/json',
                }
            })
            .then((response) => console.log(response))
            .catch((error) => console.log(error));
        },
        renderImages(event) {
            let selectedFiles = event.target.files;
            for (let i =0; i< selectedFiles.length; i++) {
                const image = selectedFiles[i];
                this.images.push({
                    id: UniqueID().getID(),
                    name: image.name,
                    file: image,
                    size: formatBytes(image.size),
                });
            }
            for (let i = 0; i < this.images.length; i++) {
                let reader = new FileReader();
                reader.onload = (event) => {
                    this.imageRefs[i].src = reader.result;
                }
                reader.readAsDataURL(this.images[i].file);
            }
        }
    }
};
</script>

my controller code from

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $post = Post::create(request()->validate([
            'title' => 'required',
            'category' => 'required',
            'photo' => 'required|image',
            'content' => 'nullable|string',
            'author' => 'nullable|string',
            'photos.*' => 'nullable|image',
            'pdf' => 'nullable|file'
        ]));
        return redirect()->route('posts.index')
                        ->with('message', 'Successfully saved');
    }

on the model i use setter to actually upload store the files

public function setPhotosAttribute($photos)
    {
        $paths = [];
        foreach($photos as $photo) {
            $paths[] = $photo->store('photos');
        }
        $this->attributes['photos'] = json_encode($paths);
    }

*** I copy pasted the codes from different projects of mine

1 like

Please or to participate in this conversation.