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

mushood's avatar
Level 41

File Upload

I have this code for my file upload:

<template>
    <div class="col-md-12">
        <div class="col-md-2">
            <img :src="image" class="img-responsive">
        </div>
        <div class="col-md-8">
            <input type="file" v-on:change="onFileChange" class="form-control">
        </div>
        <div class="col-md-2">
            <button class="btn btn-success btn-block" @click.prevent="upload">Upload</button>
        </div>
    </div>
</template>

<script>
    export default{

      mounted() {
          console.log('Component file upload mounted.');
      },

        data(){
            return {
                image: '',
                imageName: ''
            }
        },
        methods: {
            onFileChange(e) {
                let files = e.target.files || e.dataTransfer.files;
                if (!files.length)
                    return;
                this.createImage(files[0]);
                this.imageName = files[0]['name'];
            },
            createImage(file) {
                let reader = new FileReader();
                let vm = this;
                reader.onload = (e) => {
                    vm.image = e.target.result;
                };
                reader.readAsDataURL(file);
            },
            upload(){
                let vm = this;
                axios.post('/blog/image',{
                  image: this.image,
                  imageName: this.imageName
                })
                .then(response => {
                  Event.$emit('fileUploaded',{
                    filename: response.data.filename,
                  });
                })
                .catch(function (error) {
                  Vue.swal({
                    title: 'File Upload Failure!',
                    text: "File size should be less than 2Mb",
                    type: 'warning',
                    confirmButtonText: "Okay gotcha!"
                  });
                });
            }
        }
    }
</script>

This code works correctly. The steps are: 1. click and choose file 2. Click on upload

However, I would like to bypass that second click. Click and choose the file and then file upload starts automatically.

The problem is if I call the upload function in the onFileChange() or createImage(), the get this error:

 "message": "Image source not readable",
    "exception": "Intervention\Image\Exception\NotReadableException",

which tells me that the file is not ready for upload when the function executes. I set a timeout before launching the function, this works. But I would like to know what event I should actually be listening to OR how to launch the function when the file is ready

0 likes
1 reply
mushood's avatar
mushood
OP
Best Answer
Level 41

The problem was not the order of the call of the functions but rather the reader.onload() function in createImage(file)

The solution was to call the upload method in that reader.onload()

Working code:

<template>
    <div class="col-md-12">
        <div class="col-md-2">
            <img :src="image" class="img-responsive">
        </div>
        <div class="col-md-8">
            <input type="file" v-on:change="onFileChange" class="form-control">
        </div>
        <div class="col-md-2">
            <button class="btn btn-success btn-block" @click.prevent="upload">Upload</button>
        </div>
    </div>
</template>

<script>
    export default{

      mounted() {
          console.log('Component file upload mounted.');
      },

        data(){
            return {
                image: '',
                imageName: ''
            }
        },
        methods: {
            onFileChange(e) {
                let files = e.target.files || e.dataTransfer.files;
                if (!files.length)
                    return;
                this.createImage(files[0]);
                this.imageName = files[0]['name'];
            },
            createImage(file) {
                let reader = new FileReader();
                let vm = this;
                reader.onload = (e) => {
                    vm.image = e.target.result;
                    vm.upload();
                };
                reader.readAsDataURL(file);
            },
            upload(){
                let vm = this;
                axios.post('/blog/image',{
                  image: this.image,
                  imageName: this.imageName
                })
                .then(response => {
                  Event.$emit('fileUploaded',{
                    filename: response.data.filename,
                  });
                })
                .catch(function (error) {
                  Vue.swal({
                    title: 'File Upload Failure!',
                    text: "File size should be less than 2Mb",
                    type: 'warning',
                    confirmButtonText: "Okay gotcha!"
                  });
                });
            }
        }
    }
</script>

Please or to participate in this conversation.