Cara Upload Gambar di Laravel 8 dengan Vue.js

whynwd

whynwd Rabu, 26 Mei 2021

Cara Upload Gambar di Laravel 8 dengan Vue.js

Laravel menyediakan kemudahan bagi kita untuk bekerja dengan sistem file dan memiliki berbagai macam metode yang bisa kita gunakan. Kita bisa menyimpan, mengambil atau menampilkan, dan menghapus file di laravel dengan mudah dan dengan penyimpanan sistem baik local ataupun ke server cloud.

Sebagai contoh mari kita coba menggunakan file sistem mengupload atau membuat fungsi menyimpan gambar ke database.

Yang akan dibuat:

  • Membuat metode request file upload gambar di laravel
  • Membuat component vue dan element input
  • Menyimpan gambar ke public path dan database MySQL
  • Membuat permintaan http menggunakan Axios

Instalasi Laravel dan Library Vue

Kita siapkan projek terlebih dahulu. Kita install laravel, membuat tabel kolom database, dan menambahkan library vue ke projek.

Install laravel

laravel new example-app

Database

Silahkan buat database MySQL baru dan hubungkan dengan projek.

MariaDB [(none)]> create database db_images;
Query OK, 1 row affected (0.009 sec)

//.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_images
DB_USERNAME=root
DB_PASSWORD=

Membuat File Migrasi

Kita tambahkan file migrasi baru untuk tabel khusus Images.

php artisan make:model Image -m

Lalu tambahkan sebuah kolom dan lakukan migrasi.

//...create_images_table.php
public function up()
{
   Schema::create('images', function (Blueprint $table) {
     $table->id();
     $table->string('image');
     $table->timestamps();
  });
}
php artisan migrate
MariaDB [uploadimage]> show tables;
+-----------------------+
| Tables_in_uploadimage |
+-----------------------+
| failed_jobs           |
| images                |
| migrations            |
| password_resets       |
| users                 |
+-----------------------+
5 rows in set (0.001 sec)

Konfigurasi Vue

Selanjutnya kita install vue, membuat instance dan component vue.

npm install vue vue-loader vue-template-compiler --save-dev

Setelah depedensi diatas ditambahkan, silahkan buka file app.js dan buat vue instance seperti dibawah ini.

//resources/js/app.js
import Vue from 'vue';

import App from './components/App.vue'

 
new Vue({
  el: '#app',
  components: { App }
});

Kemudian buat folder baru di direktori js dengan nama components dan tambahkan sebuah component App.vue didalamnya lalu copas template dibawah ini.

//js/components/App.js
<template>
  <div class="container">
    <h1>Upload New Image</h1>
  </div> 
</template>

Selanjutnya buka file welcome.blade.php dan ubah html yang ada dengan dibawah ini.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Upload New Image</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
        <style>
            body {
                font-family: 'Nunito', sans-serif;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <app></app>
        </div> 
        <script src="{{ mix('js/app.js') }}"></script>
    </body>
</html>

Terakhir, kita buka file webpack.mix.js dan buat seperti dibawah ini kemudian lakukan compiling.

const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
 .vue();

Kita gunakan saja mix watch yang akan tetap aktif untuk meng-compile secara otomatis setiap ada perubahan pada file js kita.

npm run watch

Setelah selesai silahkan buat tab baru pada terminal lalu jalankan php artisan serve. Kemudian buka aplikasi pada browser dan kita pastikan vue.js sudah terinstal.

Cara Upload Gambar di Laravel 8 dengan Vue.js

Model, Controller, dan Route

Selanjutnya kita akan buat sebuah controller dan membuat metode permintaan, route, dan mass assignment model.

Pertama mari kita buka model Image.php dan tambahkan metode $fillable seperti dibawah ini.

...

class Image extends Model
{
    use HasFactory;

    protected $fillable = [
        'image'
    ];
}

Kemudian kita buat controller dengan nama ImageController lalu kita buat request seperti dibawah.

php artisan make:controller ImageController
//ImageController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Image;

class ImageController extends Controller
{
    public function uploadImage(Request $request)
    {
        $request->validate([
            'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg',
        ]);
         
        $name = time()."-".$request->file('image')->getClientOriginalName();

        $request->file('image')->move(public_path('images'), $name); 
       
        Image::create([ 'image' => $name ]); 
        
        return response()->json([ 
            'data'   => asset("images/$name"),
            'message' => 'Gambar baru berhasil disimpan.'
        ]); 
    }
}

Mari kita lihat controller diatas. Kita tambahkan validasi dimana value tidak boleh kosong saat mengirim permintaan dan hanya file dengan extensi jpeg, png, jpg, gif, svg yang diperbolehkan.

Kemudian kita gunakan metode getClientOriginalName() untuk menyimpan file dengan nama asli dari file tersebut, dan gambar yang berhasil disimpan akan masuk ke direktori public di dalam folder images.

Kita tidak perlu membuat folder images karena nanti akan otomatis terbuat.

Dan karena tidak bisa menyimpan gambar dengan nama yang sama, kita gunakan metode time() untuk membuat atau menambahkan nama unik ke setiap file.

Kita juga simpan file gambar ke database menggunakan metode create, dan akan menghasilkan response barupa informasi file gambar dan pesan berhasil.

Setelah metode uploadImage() diatas dibuat, selanjutnya kita buka file route web.php dan tambahkan route dibawah ini.

use App\Http\Controllers\ImageController;

Route::post('/addimage', [ImageController::class, 'uploadImage']);

Kita buka kembali component App.vue dan silahkan buat seperti dibawah ini.

<template>
  <div class="container">
    <h1>Upload New Image</h1>
    <p>{{message}}</p>  
    <div v-if="errors" class="errors">
        <p v-for="(error,index) in errors" :key="index" >{{error}}</p>
    </div>
    <div class="preview" v-if="preview">
        <p>Preview: </p>
        <img :src="preview" width="200" height="150">
    </div>
   <div>
    <input type="file" ref="file" id="file" @change="fileImage"> 
      <button class="modal-default-button" @click="uploadFile">
        Save
      </button>
     </div>
  </div>
</template>

<script>
import axios from 'axios'

export default { 
  data(){
    return {
      image : null,
      message : null, 
      preview : null,
      errors: null
    }
  }, 
  methods : {
    fileImage(event){   
      this.image = event.target.files[0];  
      this.preview = URL.createObjectURL(event.target.files[0]);  
    },
    uploadFile(event){  
      var formData = new FormData();
        formData.append("image", this.image)
        axios.post("/addimage", formData)
        .then(response => {
            this.image = response.data.data
            this.message = response.data.message
            this.preview = null
            this.$refs.file.value = null;
            this.errors = null 
            
            //console.log(response);
        })
        .catch(error => {
            this.errors = error.response.data.errors.image 
            this.message = null
        }) 
      }
    }
  }
</script>

<style scoped>
  .container{
    border: 1px solid;
    width: 28rem;
    margin: 2rem auto 0;
    padding: 2rem;
  }
   
  .errors{
    color: #f44336;
  }
  h1{
    margin-top: 0;
  }
</style>

Kita gunakan metode URL.createObjectURL untuk menghasilkan url dari object file gambar yang dipilih yang kita gunakan untuk membuat preview sebelum dikirim, dan $refs untuk mengakses value inputan untuk dikosongkan setelah berhasil mengirim permintaan.

Sekarang mari kita mencobanya. Silahkan coba untuk upload gambar baru dan coba juga munculkan validasi dengan mengirim permintaan tanpa gambar.

Hasilnya seperti gambar dibawah ini.

Cara Upload Gambar di Laravel 8 dengan Vue.js

Setelah berhasil mengirim gambar, silahkan buka folder images di direktori public dan juga database untuk melihat file gambar yang tersimpan.

Selesai. Kita sampai disini, silahkan dicoba dan dikembangkan.

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel