Rod2rick's avatar

Laravel 8 vuejs image doesn't upload and save to database

Like the title says, i can't upload image and save it to database. here is my controller

public function store(Request $request)
    {
     
        $request['data'] = json_decode($request['data']);
        $produit = new Produits;
        $produit->nom     = $request->get('nom');
        $produit->description   = $request->get('description');
        $produit->prix = $request->get('prix');
        $produit->type = $request->get('type');
        $produit->categories_id = $request->get('categories_id');
        $produit->users_id =  $request->get('users_id');
        if ($request->hasfile('image')) {
            $image = $request->file('image');
            $filename = $produit->nom . '_' . time() . '.' . $image->getClientOriginalExtension();
            if ($produit->image && $produit->image == 'noproductimage.jpg') {
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            } else {
                File::delete(public_path('/uploads/produits/' . $produit->image));
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            }
            $produit->image = $filename;
        }
        $produit->save();
        return response()->json(['success' => 'Produit enregistré avec succès']);
    }

and this my vue

<form @submit.prevent="store" enctype="multipart/form-data">
                <div class="form-group row">
                  <label></label>
                  <input
                    class="form-control"
                    type="text"
                    placeholder="Nom du produit"
                    v-model="nom"
                    required
                    autofocus
                  />
                </div>

                <div class="form-group row">
                  <label></label>
                  <textarea
                    class="form-control"
                    id="textarea-input"
                    v-model="description"
                    rows="6"
                    placeholder="Description du Produit"
                    required
                  ></textarea>
                </div>

                <div class="form-group row">
                  <div class="col-md-9">
                    <input
                      id="file-input"
                      placeholder="Image du produit"
                      type="file"
                      name="image"
                      @change="onFileChange"
                      v-on:change="image"
                    />
                  </div>
                </div>

                <button
                  class="btn btn-block pull-right btn btn-sm btn-outline-info"
                  type="submit"
                >
                  {{ "Valider" }}
                </button>
                <a href="" class="btn btn-block btn btn-sm btn-info">
                  {{ "Retourner" }}
                </a>
              </form>
--------------

<script>
export default {
  data() {
    return {
      
      nom: "",
      description: "",
      image: ""
    };
  },
  methods: {
        onFileChange(e) {
      //console.log(e.target.files[0]);
      this.image = "L'image sélectionnée: " + e.target.files[0].name;
      this.image = e.target.files[0];
    },
    store() {
      const config = {
        headers: {
          "content-type": "multipart/form-data",
          "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').content,
        },
      };
      axios
        .post("/api/createproduit", {
          nom: this.nom,
          description: this.description,
          image: this.image,
        })
        .then((response) => {
          this.produits = response.data.data;
          this.loading = false;
          this.form.reset();
          window.location = response.data.redirect;
        })
        .then(location.reload())
        .catch(function (error) {
          console.log(error);
        });
    },
  },
  mounted() {
    this.getCategories();
  },
};
</script>

what do i do wrong so that the image connot be saved.

0 likes
18 replies
mvd's avatar

Hi @rod2rick

Add

headers: {
  'Content-Type': 'multipart/form-data'
}

In your Axios request

axios.post("/api/createproduit", {
          nom: this.nom,
          description: this.description,
          image: this.image,
        }, headers: {
    'Content-Type': 'multipart/form-data'
    })
        .then((response) => {
    this.produits = response.data.data;
    this.loading = false;
....
....

Or


            let formData = new FormData();
            formData.append('file', this.image);  

            this.axios.post('/api/createproduit',

                formData,
                {
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
              }
.....

Rod2rick's avatar

@mvd I did it but nothing, it save the data well, but not the images.

mvd's avatar

@rod2rick no errors in the logs?

Your upload code looks fine.

Did you set some dumps/dd code in your upload code for debugging?

Example:

if ($request->hasfile('image')) {
	dump('has file');	
            $image = $request->file('image');
            $filename = $produit->nom . '_' . time() . '.' . $image->getClientOriginalExtension();
            if ($produit->image && $produit->image == 'noproductimage.jpg') {
	dump('in if');
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            } else {
	dump('in else');
                File::delete(public_path('/uploads/produits/' . $produit->image));
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            }
            $produit->image = $filename;
        }
dd('end debugging');
hdsavani's avatar

Can you tell me what error or what issue comes when you try that code?

Rod2rick's avatar

@hdsavani No error is generated, the system saves the data well, but does not save the image.

EckyEckyPtang's avatar

Because it's a pile of garbage that is polluting the web

The guy can barely speak English, it's just code snippets copy-pasted from Stack Overflow, without any explanation on how it works.

And the domain is IT Solution Stuff dot com -lmao. Never take lessons from these type of Indian spam blogs.

Rod2rick's avatar

@mvd , @hdsavani , I was able to fetch the image and save it to the product table, but in a way that I ignore the image is not fetched and save in the path. nb: this code works with blade without vuejs, but as soon as i integrate it with vuejs, it doesn't save the image. Please help me.

my code : my controller

public function store(Request $request)
    {
        $request['data'] = json_decode($request['data']);
        $produit = new Produits;
        if ($request->hasfile('image')) {
            $image = $request->file('image');
            $filename = $produit->nom . '_' . time() . '.' . $image->getClientOriginalExtension();
            if ($produit->image && $produit->image == 'noproductimage.jpg') {
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            } else {
                File::delete(public_path('/uploads/produits/' . $produit->image));
                Image::make($image)->resize(500, 500)->save(public_path('/uploads/produits/' . $filename));
            }
            $produit->image = $filename;
        }
        $produit->nom = $request->get('nom');
        $produit->description = $request->get('description');
        $produit->prix = $request->get('prix');
        $produit->type = $request->get('type');
        $produit->categories_id = $request->get('categories_id');
        $produit->users_id = $request->get('users_id');
        $produit->image = $request->get('image');
        $request->file('image')->store('pictures');
        $produit->save();
        return response()->json(['success' => 'Produit enregistré avec succès']);
    }

my vuejs page

<template>
  <div class="container-fluid">
    <div class="animated fadeIn">
      <div class="row">
        <div class="col-sm-12 col-md-10 col-lg-8 col-xl-6">
          <div class="card">
            <div class="card-header">
              <i class="fa fa-align-justify"></i>
              {{ "Créer un Produit" }}
              <span class="badge float-right">
                <a
                  v-bind:href="'/listproduits'"
                  class="btn btn-sm btn-outline-info"
                  title="Liste des produits"
                >
                  <i class="fas fa-list"></i>
                </a>
              </span>
            </div>

            <div class="card-body">
              <form @submit.prevent="store" enctype="multipart/form-data">
                <div class="form-group row">
                  <label></label>
                  <input
                    class="form-control"
                    type="text"
                    placeholder="Nom du produit"
                    v-model="nom"
                    required
                    autofocus
                  />
                </div>

                <div class="form-group row">
                  <label></label>
                  <textarea
                    class="form-control"
                    id="textarea-input"
                    v-model="description"
                    rows="6"
                    placeholder="Description du Produit"
                    required
                  ></textarea>
                </div>

                <div class="input-group row">
                  <label></label>
                  <input
                    type="text"
                    class="form-control"
                    v-model="prix"
                    placeholder="Prix du produit"
                  />
                  <div class="input-group-append">
                    <span class="input-group-text">FCFA</span>
                  </div>
                </div>

                <div class="form-group row">
                  <label>Categories:</label>
                  <select
                    class="form-control"
                    v-model="categories_id"
                    @change="getCategories()"
                  >
                    <option disabled value="">
                      Sélectionner une catégorie
                    </option>
                    <option
                      v-for="categorie in categories"
                      v-bind:key="categorie.id"
                      v-bind:value="categorie.id"
                    >
                      {{ categorie.nom }}
                    </option>
                  </select>
                </div>

                <div class="form-group row">
                  <div class="col-md-9">
                    <input
                      id="file-input"
                      placeholder="Image du produit"
                      type="file"
                      name="image"
                      @change="onFileChange"
                      v-on:change="image"
                    />
                  </div>
                </div>

                <div class="form-group row">
                  <label></label>
                  <input
                    class="form-control"
                    type="text"
                    placeholder="Type du produit"
                    v-model="type"
                    required
                    autofocus
                  />
                </div>

                <div class="form-group row">
                  <label></label>
                  <input
                    class="form-control"
                    type="hidden"
                    placeholder=""
                    v-model="users_id"
                    required
                    autofocus
                  />
                </div>

                <button
                  class="btn btn-block pull-right btn btn-sm btn-outline-info"
                  type="submit"
                >
                  {{ "Valider" }}
                </button>
                <a href="" class="btn btn-block btn btn-sm btn-info">
                  {{ "Retourner" }}
                </a>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      categories_id: "",
      categories: [],
      nom: "",
      description: "",
      prix: "",
      type: "",
      image: "",
      users_id: document
        .querySelector("meta[name='users_id']")
        .getAttribute("content"),
    };
  },
  methods: {
    getCategories: function () {
      axios.get("/api/get_categories").then(
        function (response) {
          this.categories = response.data;
        }.bind(this)
      );
    },
    onFileChange(e) {
      //console.log(e.target.files[0]);
      this.image = e.target.files[0].name;
      this.file = e.target.files[0];
    },
    store() {
      axios
        .post("/api/createproduit", {
          // /api/createproduit = au chemin depuis route -> api.php
          nom: this.nom,
          description: this.description,
          prix: this.prix,
          type: this.type,
          image: this.image,
          categories_id: this.categories_id,
          users_id: document
            .querySelector("meta[name='users_id']")
            .getAttribute("content"),
          headers: {
            "content-type": "multipart/form-data",
            "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]')
              .content,
          },
        })
        .then((response) => {
          this.produits = response.data.data;
          this.loading = false;
          this.form.reset();
          window.location = response.data.redirect;
        })
        .then(location.reload())
        .catch(function (error) {
          console.log(error);
        });
    },
  },
  mounted() {
    this.getCategories();
  },
};
</script>

<style></style>

Thank you in advance for your help.

MarianoMoreyra's avatar
Level 25

Hi @rod2rick

You are able to save the filename because it's all that you are sending about the file. Here:

    onFileChange(e) {
      //console.log(e.target.files[0]);
      this.image = e.target.files[0].name;
      this.file = e.target.files[0];
    },

You are assigning the selected file to this.file but you never use that variable again at the moment of sending with axios.

Change that method to:

    onFileChange(e) {
      this.image = e.target.files[0];
    },

Then, at your store() method, you should encapsulate all the fields, including the file, inside a FormData object, otherwise, Laravel won't be able to decode the image (you should encode it in base64 at javascript before sending it, and decoding from base64 at your Laravel Controller):

    store() {
      const data = new FormData();

      data.append('nom', this.nom);
      data.append('description', this.description);
      data.append('prix', this.prix);
      data.append('type', this.type);
      data.append('image', this.image);
      data.append('categories_id', this.categories_id);
      data.append('users_id', document
            .querySelector("meta[name='users_id']")
            .getAttribute("content"));

      axios
        .post("/api/createproduit", data)
        .then((response) => {
          this.produits = response.data.data;
          this.loading = false;
          this.form.reset();
          window.location = response.data.redirect;
        })
        .then(location.reload())
        .catch(function (error) {
          console.log(error);
        });
    },
  },

Please let me know if this worked!

Rod2rick's avatar

@marianomoreyra , I tried your code, but unfortunately it doesn't work 100%. Unlike my code, It does save the image in folder, but does not save the product in the database. Having tried to recover your code mix with mine nothing, this time no data, neither the image, nor the data is recorded.

MarianoMoreyra's avatar

Hi @rod2rick

Try commenting the following line out at your Controller:

json_decode($request['data']);

Since you shouldn’t need to decode when using FormData method.

Rod2rick's avatar

@marianomoreyra Nothing have changed, it save the image in the storage, but nothing in the database. How can we explain that

store() {
      axios
        .post("/api/createproduit", {
          // /api/createproduit = au chemin depuis route -> api.php
          nom: this.nom,
          description: this.description,
          prix: this.prix,
          type: this.type,
          image: this.image,
          categories_id: this.categories_id,
          users_id: document
            .querySelector("meta[name='users_id']")
            .getAttribute("content"),
          headers: {
            "content-type": "multipart/form-data",
            "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]')
              .content,
          },
        })
        .then((response) => {
          this.produits = response.data.data;
          this.loading = false;
          this.form.reset();
          window.location = response.data.redirect;
        })
        .then(location.reload())
        .catch(function (error) {
          console.log(error);
        });
    },
  },

saves in the database without save the image and

store() {
        const data = new FormData()

      data.append('nom', this.nom)
      data.append('description', this.description)
      data.append('prix', this.prix)
      data.append('type', this.type)
      data.append('image', this.image)
      data.append('categories_id', this.categories_id)
      data.append('users_id', document
            .querySelector("meta[name='users_id']")
            .getAttribute("content"))
      axios
        .post("/api/createproduit",data)
        .then((response) => {
          this.produits = response.data.data;
          this.loading = false;
          this.form.reset();
          window.location = response.data.redirect;
        })
        .then(location.reload())
        .catch(function (error) {
          console.log(error);
        });
    }

did not save anything. Hum it's really frustrating.

MarianoMoreyra's avatar

@rod2rick if the file is getting saved to storage but not saving on database, it's probably because you are getting an error when saving to database.

Check the network tab on Developer Tools and see if the ajax POST is getting a 500 error. If that's the case, you should click on the corresponding post and check the Response tab to see if you get an error description.

Rod2rick's avatar

@marianomoreyra unfortunately the network console does not return any error. It recharges without sending an error

Rod2rick's avatar

@marianomoreyra I found the problem preventing the item from being saved to the database. I found the problem preventing the item from being saved to the database. So, I added in config-> App.php this lines 'providers' => Intervention\Image\ImageServiceProvider::class, 'Image' => Intervention\Image\Facades\Image::class, and now it save and image to folder and items to database. Thank you for your precious help..

Please or to participate in this conversation.