juanitourquiza
juanitourquiza

Reputation: 2194

How to upload image from VueJS to Symfony with Axios?

I have the VueJS component installed without problem in my project with Symfony 4 but at the moment I want to upload an image. I follow this reference from Laravel: How to upload image from VueJS to Laravel with Axios?

I get to the controller but that's where the value in base 64 does not reach just the console message.

Code:

//CargaFoto.vue
<template>
    <div class="hello">
        <h1>{{ msg }}</h1>
        <input type="file" name="image" @change="getImage" accept="image/*">
        <button @click="updateAvatar">Subir Imagen</button>
        </div>
    </div>
</template>

<script>
    import axios from 'axios'

    export default {
        name: "CargaFoto",
        data() {
            return {
                msg: "Cargar Imagen de Perfil",
                imagen: null
           };
        },
        methods: {
            getImage(event){
            //Asignamos la imagen a  nuestra data
            this.imagen = event.target.files[0];
        },
        updateAvatar(){
            //Creamos el formData
            var data = new  FormData();
            data.append('avatar', this.imagen);
            data.append('_method', 'POST');
            //Enviamos la petición
            axios.post('/usuario/jsonimagen',data)
                .then(response => {
                    console.log(res)
                })
        }
</script>

And this the controller code:

/**
 * @return JsonResponse
 * @Route("/jsonimagen", name="jsonimagen", methods="POST")
 */
public function jsonimagen(Request $request):JsonResponse
{

    $data= $request->get("data");
    return $this->json($data);
}

The answer is null The doubt that I have is how I upload the image to the local server.

Upvotes: 3

Views: 3957

Answers (2)

juanitourquiza
juanitourquiza

Reputation: 2194

Based on the link of a comment indicated by Fran I could see that the header was missing and then collect the data in Symfony in the same route that was already defined.

The template file was like this:

//CargaFoto.vue
<template>
    <div class="hello">
        <h1>{{ msg }}</h1>
      <div class="container">
            <div class="large-12 medium-12 small-12 cell">
                <label>File
                    <input type="file" id="file" ref="file" v-on:change="handleFileUpload()"/>
                </label>
                <button v-on:click="submitFile()">Submit</button>
            </div>
        </div>

        </div>
    </div>
</template>

<script>
    import axios from 'axios'

    export default {
        name: "CargaFoto",
        data() {
            return {
                msg: "Cargar Imagen de Perfil",
                file: ''
                //selectedFile: null
            };
        },
        methods: {
            submitFile(){
                /*
                        Initialize the form data
                    */
                let formData = new FormData();

                /*
                    Add the form data we need to submit
                */
                formData.append('file', this.file);

                /*
                  Make the request to the POST /single-file URL
                */
                axios.post( '/usuario/jsonimagen',
                    formData,
                    {
                        headers: {
                            'Content-Type': 'multipart/form-data'
                        }
                    }
                ).then(function(){
                    console.log('SUCCESS!!');
                })
                    .catch(function(){
                        console.log('FAILURE!!');
                    });
            },

            /*
              Handles a change on the file upload
            */
            handleFileUpload(){
                this.file = this.$refs.file.files[0];
            }
        }
    };
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
    #fileInput {
        display: none;
    }
    h1,
    h2 {
        font-weight: normal;
    }
    ul {
        list-style-type: none;
        padding: 0;
    }
    li {
        display: inline-block;
        margin: 0 10px;
    }
    a {
        color: #42b983;
    }
    .my-8 {
        margin-top: 4rem;
        margin-bottom: 4rem;
    }
</style>

In the file where the data is request, the controller is:

//src/UsuarioController.php
/**
 * @return JsonResponse
 * @Route("/jsonimagen", name="jsonimagen", methods="POST")

 */
public function jsonimagen(Request $request):JsonResponse
{
    $usuario = $this->getUser();
    $data = $request->files->get('file');
    $fileName = $usuario.'.'.$data->guessExtension();
    // moves the file to the directory where usuarios are stored
    $data->move(
        $this->getParameter('usuarios_directorio'),
        $fileName
    );
    echo $data; exit;
    return $this->json($data);
}

Also configure the path where the images will be loaded in the file

//services.yaml
parameters:
    locale: 'en'
    usuarios_directorio: '%kernel.project_dir%/public/uploads/usuarios'

Here you can see the image loaded in this capture.

enter image description here

Upvotes: 2

Styx
Styx

Reputation: 10076

You're sending file content as avatar variable, why do you try to get request's data then?

Correct form would be:

$avatar = $request->file('avatar');

Also, you can omit adding _method: 'POST' to sent data as you're doing axios.post already.

Upvotes: 1

Related Questions