The combination of Laravel 9 and Vue.js 3 provides a powerful platform for building modern web applications. One of the most common requirements for web apps is the ability to upload images. In this article, we will explain the steps necessary to upload an image from a Vue form Laravel storage.
Note: this process relies on Inertia.js. If your project doesn't use Inertia, you'll need to make several changes regarding form submission and data transmission.
For simplicity, we won't be going over creating a project, but you can check out our article about starting a Laravel & Vue.js project Here.
Create the Vue Form
Set up Laravel Routing and Controller
Displaying the image in Vue.js.
Deleting the image (optional).
Create the Vue.js Form
In Vue, we will use the Inertia.js useForm form helper to handle the file upload. create a new Vue component that will contain the file upload form and add the following code:
<template>
<form @submit.prevent="submit">
<input type="file" name="image" id="image"
@input="form.imgurl = $event.target.files[0]" />
<button type="submit">Upload</button>
</form>
</template>
In the component's script tag, we'll need to import the useForm
function from @inertiajs/inertia-vue3
.
<script>
import { useForm } from "@inertiajs/inertia-vue3";
const form = useForm({
imgurl: "",
});
methods: {
submit() {
form.post(route("upload"), {
forceFormData: true,
onSuccess: () => {
form.reset(
"imgurl",
);
let file = document.getElementById("image");
file.value = null;
},
});
}
}
</script>
In this code, the submit
method makes a POST
request to the /upload
route with the uploaded file. With our file being sent, let's see how to store it.
Set up Laravel Routing and Controller
Before We get into the Laravel Code, we need to set a symbolic link in our storage directory using the following command:
php artisan storage:link
In Laravel, we need to set up a route and a controller that will handle the file upload. To create a new route, open the routes/web.php
file and add the following code:
// Web.php
use App\Http\Controllers\FileUploadController;
Route::post('/upload', [FileUploadController::class, 'store']);
Next, create the controller by running the following command:
$ php artisan make:controller FileUploadController
Open the newly created FileUploadController
and add the following code to the store method:
// FileUploadController.php
use Illuminate\Http\Request;
class FileUploadController extends Controller{
public function store(Request $request){
$request->validate([
'imgurl' =>'required|image|mimes:jpg,png,jpeg,gif|max:2048',
]);
$image_path = $request->file('imgurl')->store('images','public');
}
}
This process verifies if the image meets the specified conditions, and if it does, it creates a new images
directory within the storage/app/public
folder located in the root directory of our application. The image is then saved in this newly created directory and a file path is returned, which we store in the $image_path
variable.
To utilize the image in the future, we need to save its path in our database.
// FileUploadController.php
use App\Models\Images;
use Illuminate\Http\Request;
class FileUploadController extends Controller{
public function store(Request $request){
$request->validate([
'imgurl' =>'required|image|mimes:jpg,png,jpeg,gif|max:2048',
]);
$image_path = $request->file('imgurl')->store('images','public');
$record = new Images([
'imgurl' => asset('storage/'.$image_path),
]);
sleep(1);
$record->save();
return Redirect::route('gallery');
}
}
In this example, the Image
model serves as a placeholder that should be substituted with your own implementation and includes a fillable field of imgurl
.
Displaying the image in Vue.js.
Now, there are several ways to fetch the image path from the database. Feel free to use whichever way fits your needs as long as the data is made available in the Vue component. For simplicity, we will use a method that fetches all Images
and renders a Gallery page.
use Inertia\Inertia;
class FileUploadController extends Controller{
public function index(){
$images = Images::->get();
return Inertia::render('Gallery', ['images' => $images]);
}
}
// Web.php
use App\Http\Controllers\FileUploadController;
Route::get('/gallary', [FileUploadController::class, 'index'])
->name('gallery');
This renders the Gallery page and passes the data from the model as a prop that can be accessed within the page.
To display the images all that is left is to loop over the images object and render them in the img
element
// Gallery.vue
<script>
export default{
props:{
images: Object;
}
}
</script>
<template>
<div v-for="image in images" :key="image.id">
<img :src="image.imgurl" />
</div>
</tepmlate>
Deleting the image (optional)
Now that we stored and displayed the image, it is very common to want to delete it. This requires deleting the image from the storage folder and the record from the database.
In the gallery page, we need to send the Id
of the image to be deleted to the backend.
// Gallery.vue
<script>
import { Link } from "@inertiajs/inertia-vue3";
export default{
props:{
images: Object;
}
}
</script>
<template>
<div v-for="image in images" :key="image.id">
<img :src="image.imgurl" />
<Link :href="route('delete')" method="post" as="button" :data="{id :image.id}"> Delete image </Link>
</div>
</tepmlate>
Next, setup the delete
route and controller to handle the request
// Web.php
Route::post('/delete', [FileUploadController::class, 'destroy'])
->name('delete');
$id = $request->get('id');
$imgurl = Images::where('id', $id)->limit(1)->get('imgurl');
$imagename = substr($imgurl[0]['imgurl'], strpos($imgurl[0]['imgurl'], 'images/') + 7);
@unlink('storage/images/' . $imagename);
DB::table('images')->Where('id', $id)->delete();
return redirect('gallery')->with('success', 'Image Deleted');
We start by retrieving the value of the "id" query parameter from the incoming HTTP request using the $request->get
method. The method then queries the images
table to obtain the imgurl
value of the image record with the same id
value.
The image name is extracted from the imgurl
value and the actual image file is deleted from the storage/images/
directory using the unlink
function. Finally, the method deletes the image
record from the images
table and returns a redirect response to the gallery
page.
Conclusion
With that, we have reached the end of this article discussing image upload in Laravel and Vue. If you have any further questions or need clarification, please don't hesitate to ask in the comments section. We hope this information was helpful and until next time.