Laravel Inertia Course Upload or upload files changes in the controller
In this chapter we are going to learn how file upload works in Laravel Inertia as you can imagine everything that has to do with the backend in Laravel remains exactly the same and it is in the client that we have the changes to be able to use the file upload integration from Inertia
From Editvue view
Initially we are going to handle file uploads specifically image uploads for posts independently of the form we already have for editing we will use the Savevue form by placing a conditional only for editing
app/Http/Controllers/Dashboard/PostController.php
public function edit(Post $post)
{
$categories = Category::get();
return inertia("Dashboard/Post/Edit", compact('post', 'categories'));
}
We are going to create the disk where the images of the publications will be loaded which would be in the public folder
config/filesystems.php
'public_upload' => [
'driver' => 'local',
'root' => public_path(),
],
The controller for loading images is normal applying validations
$request->validate(
[
'image' => 'required|mimes:jpg,jpeg,png,gif|max:10240'
]
);
Delete the old image if it exists
Storage::disk("public_upload")->delete("image/post/".$post->image);
Generate a random image name
time()."." .$request['image']->extension();
Move to public folder
$request->image->move(public_path("image/post"),$filename);
And update the post
$post->update($data);
Finally we have
app/Http/Controllers/Dashboard/PostController.php
***
use Illuminate\Support\Facades\Storage;
***
public function upload(Request $request, Post $post)
{
$request->validate(
[
'image' => 'required|mimes:jpg,jpeg,png,gif|max:10240'
]
);
Storage::disk("public_upload")->delete("image/post/" . $post->image);
$data['image'] = $filename = time() . "." . $request['image']->extension();
$request->image->move(public_path("image/post"), $filename);
$post->update($data);
return to_route('post.index')->with('message', "Upload image to post successfully");
}
We create the route
routes/web.php
Route::group(['middleware' => [
'auth:sanctum',
'prefix' => 'dashboard',
config('jetstream.auth_session'),
'verified',
]], function () {
Route::resource('/category', App\Http\Controllers\Dashboard\CategoryController::class);
Route::resource('/post', App\Http\Controllers\Dashboard\PostController::class);
Route::post('/post/upload/{post}', [App\Http\Controllers\Dashboard\PostController::class,'upload'])->name('post.upload');
});
In the edit form we define a prop for the image
const form = useForm({
// ***
category_id: props.post.category_id,
image: "",
});
And now we are going to place an additional block to handle the file upload as mentioned before the image upload will be done independently of the update form
resources/js/Pages/Dashboard/Post/Save.vue
<div v-if="post.id != ''">
<div class="container">
<div class="card">
<div class="card-body">
<div class="grid grid-cols-2 gap-2">
<div class="col-span-6">
<InputLabel value="Image" />
<TextInput type="file" @input="form.image = $event.target.files[0]" />
<InputError :message="errors.image" class="mt-2" />
<PrimaryButton @click="upload">Upload</PrimaryButton>
</div>
</div>
</div>
</div>
</div>
</div>
</AppLayout>
***
setup(props) {
const form = useForm({
// ***
image: "",
});
function submit() {
router.put(route("post.update", form.id), form);
}
function upload() {
router.post(route("post.upload", form.id), form);
}
return { form, submit, upload };
},
The code above is simple a file type field with its button which calls a function called upload in which we send the form just as we do when a record is updated it is important to note that to use the file upload it must be a POST type request if you want to use the file upload in another type of requests such as DELETE PATCH or PUT you must use the POST type request and specify the method in question we will see this later
router.post(route(***), {
_method: "put",
// tus datos
},
With this we will have fully functional file upload
Video Transcript
The next step that we are going to see is how to carry out the upload process that is what we are going to deal with in this section So here I show you a little of what we are going to do as always in life you have many ways to implement it I am going to show you the one that I implement since I always place it as an optional step therefore I have to do some implementations or we are going to do some implementations based on that then among this first part of optional would be that the record has to exist to be able to enable what is the upload although this will be seen more clearly when we are implementing the changes in the edit part Meanwhile here we are going to how I want to upload the resources to the path we have to create a Driver that indicates that it is local that is local to the project Remember that we can use here what would be external services such as the son web server So here the configurations would be placed but there is the local one we put local and the location is the pipat that is the public folder And from there we place an l the folders that we want but this is like who says the root once this is configured we create it which would be the validation in this case I am doing it through the request object directly in the controller because it is again optional and I am not going to place it as a mandatory part of the process as always we have to delete the previous image to avoid saving garbage and filling our server there without eh with resources that we are not going to use then that is why before loading we look if the post has an image and we delete it here you can give it any name you can also keep the local name of the natural image but as it can be repeated to avoid problems I give it a unique name and in this case we use the Time function to generate a unique name based on time Remember that this gives us the time in milliseconds since 1900 and something so it is always unique then we also move it to the what is the image that we are going to load once the previous one is deleted Remember that this is the previous one the one that has the post right now see the complete code anyway we move it to its location since at the moment it is in memory or in a temporary location in our application then we move it to its location which again is path and the image and post folders to give an example
$request->image->move(public_path("image/post"), $filename);
Although here you can place any other finally we update the post and that would be all and here it shows you the process that is the one we are going to implement here we create the route and then we see the client part that is the Vue component but with this we already have work So lets start here I am going to open Here I am going to implement it here in the dep as you could see then we are going to create a method called unat I place Pit here Well now to place F here I place loat well we already have it here obviously we receive what is the request we place request request Remember that the request although we do not use it directly here but it is already defined by default you should have it well as it is not I think I deleted it control space illuminate http request it is that well from here what we are going to do would be to create a validation that is here local to request for that here we use the validate method and here we indicate the name of the parameter as always in this case I am going to call it as image since we are going to load it is an image and here you place what you want since again although it is optional if we are going to enter this controller obviously we want to use the image resource here and that is why I put it here as mandatory since again optional is to call the method but once in the method it would be mandatory it has all the logic there you have to place the mimes place the ones you want I am going to place the most common jpg jpeg png gif and this would be all here and a maximum of 1024 kb I put two points here and that would be all
$request->validate(
[
'image' => 'required|mimes:jpg,jpeg,png,gif|max:10240'
]
);
So here I put the semicolon down here and now the next step is to Access the disk Im going to look for the System disk here and Im going to create the Path disk here This works for me I clone it here and put public here the name you prefer I think that was the name I gave it Although it can be customizable again the Driver will be local I remove this and here Im going to put that the Root that is the root will be public
'public_upload' => [
'driver' => 'local',
'root' => public_path(),
],
This is so we can use the disk function for and all that So it is better to do it like this since this is also from basic Laravel Well here there was also a similar one here we already have it So now we can close here and continue Then the next step would be to Access the disk we place here dis sorry I think that up here I also missed the post the post that we are going to edit I put here comma post Sorry for this because again the post has to exist so you can also adapt it more easily if you also want to use it to create well We are going to Access the public disk that we created before And from here we are going to delete the previous image from the image location which is going to be the one we are going to use that is here our images are going to be so here I put dot dollar post image so that it accesses the image that we have there
Storage::disk("public_upload")->delete("image/post/".$post->image);
in case it exists if it doesnt exist nothing happens it doesnt delete anything but if it exists it will Delete this would be again the previous image since notice that we are simply referencing it then here we import this one which would be illuminate Support store there we have it and here we would delete the image again well What is the next step now to work with the Data or the image that we have in the request So Im going to start here to compose it in a Data object so that we can easily update it later Im going to grab the name here or rather This is also going to be equal to name to be able to manipulate it which is going to be equal to Time
time()."." .$request['image']->extension();
Remember that these are two equalities that is it is like placing Data equal to fill name and then you can evaluate it to this You can do all this in one step We place the very important point to place the extension We place point request image and extension voltage here There it goes and here we have the name of the image in the Time function it does not want to find it Sorry it is time without this the next step is to update Here we place post update and we place the Data here
$post->update($data);
Im seeing that this is not necessary so Im going to remove it were not going to expand anything on the F name and this would be all for here the next thing would be to make some redirection to Road and we can go to the post index for example post point Index we pass the message with lets remember that it is called here as message we indicate eh successful load and this would be practically everything although here Im seeing that I didnt miss an apology I didnt miss Here we also move the image so here we place request image
$request->image->move(public_path("image/post"),$filename);
Here Im going to put the move and here Im going to put the path again we put the image post its the same as accessing like this what happens is that this is to manipulate the disk and is to access the path which is the location of our disk and the image post folder in particular and this returns the route and over here Well here you can keep the name if you want or you put this directly I think Im going to put it F name again to make it cleaner I was missing the equality and here I put it name here is where it was missing well this would be all then we eliminate the previous one we generate the new name of the image and with this we move it to this location to the final location where we are going to store our image and finally here we save the image or the name of the image in the database Now we need to create the route So we open here the web we are going to grab one of these Im going to put that the request is of type post here it is going to be post one and we pass the pos parameter and over here we have to place this in an array to be able to place the name of the method we place this and here the method is called like that and we can give it a name here that is the one of and this would be for Practically everything now with this we create the schema on the server that is the Laravel client would be missing but in order not to extend this further we will leave it for the next class So lets go
Video Transcript
Now we are going to complete the upload process here in the client in the edit section well in this case it would be the edit section if it is the one that if not use the scheme that we presented before although here I am going to place the save section because it is the one that we have merged So it shows you a little of the process I go back up here we did all this it would be missing here in the client we create a new field within the form and over here Although it seems like a lot of html this is to organize everything this block and this one over here we place the Label here the input Okay
<TextInput type="file" @input="form.image = $event.target.files[0]" />
<InputError :message="errors.image" class="mt-2" />
<PrimaryButton @click="upload">Upload</PrimaryButton>
Here remember that it is another syntax I am updating but here it is a bit the same here in the input which is the value we are going to place it through this object we access the user event the event in this case click since it is of type input and we access the target and finally here to a file since we are interested in only one file the syntax is a bit rad but right now we are going to see how it works what are we going to receive but here the important thing is that you notice that we are sending is a file through fields in position zero since we can pass several but in this exercise it would be only one Show form errors and Well finally here the click button to activate the upload process which is to make a post type request according to what we did previously passing the corresponding Data
<PrimaryButton @click="upload">Upload</PrimaryButton>
Here too in case it is necessary for you you can also make requests or send files in delete Patch and put type requests For that remember to place the method here just as it happened with Laravel when I wanted to simulate another type of request within a form Well for the rest we are going to have this which is the profile type input that we created here So lets go there to see what happens We are going to return here to the save one and again I only want to use this for when we are going to update So here we have to place a conditional just as we did before Here I am going to allow this to be copied Here I am going to place a conditional I place
<div v-if="post.id != ''">
Then we show the following content
<div v-if="post.id != ''">
<div class="container">
<div class="card">
<div class="card-body">
<div class="grid grid-cols-2 gap-2">
<div class="col-span-6">
<InputLabel value="Image" />
<TextInput type="file" @input="form.image = $event.target.files[0]" />
<InputError :message="errors.image" class="mt-2" />
<PrimaryButton @click="upload">Upload</PrimaryButton>
</div>
</div>
</div>
</div>
</div>
</div>
But anyway Im going to leave it a little simpler like this Okay so we dont forget were going to create the field for the image here Ill put image and there we have it we come back here and we need to do some things as I was telling you This is going to be an isolated process now that Im looking at this we also have to remove it from the form because if not we can have problems with the clit element so I better remove it from here Im going to place it down here to see why the style is broken Okay now Ill finish checking okay here we are here I selected one to create Nothing happens in conditional base and here in edit I think its this little thing lets see There it is its down here since I want it to escape from the form its the section form that we have here well we continue a little with this then here a little bit what is the magic or the strange thing is to place the input here which is an event that we can have in the input and that allows us to establish the value Remember that this is going to be executed when we paste and select a file that is to say when we click on this button and lets select the file this will execute this event that we have here just like it happens with a clit event remember When we have a roba it means that it is an event and in this case the event is called input according to what we have in inertia you can also see this here if you put for example input I will put inertia here you also have The exercise is the one we are doing and here you have it it is basically the same the name of the field of the form and here the stable is this here you can also put an alert or something so you can see when it is executed But anyway I dont want to extend this too much So here we put form pun image it will be the same and here it would be only the first one like every event that is to say this is again an event we have here excuse the redundancy an event in which we have information about what happened and in this case about the loading of the file and to access it we have to put target here and this is how it is structured it would be Target dot fills and here we would have what is finally our files that we have selected but we are interested in it is only one and this would be everything over here Sorry This goes I placed it in the Field errors goes obviously up here and this would be all over here we return perfect Now we need to implement the button here so we place our button
<TextInput type="file" @input="form.image = $event.target.files[0]" />
<InputError :message="errors.image" class="mt-2" />
<PrimaryButton @click="upload">Upload</PrimaryButton>
Thats all so Im going to reload to see that we have nothing wrong Before it was a warning because the method or the function did not exist and we were missing testing here Well a little bit pasted you can see that at least the method is calling this required field and this is thanks to the validations that we placed for the request Im going to look here for some for example this one some image that I have around there Okay here we have a problem this is in the event It should be in the event
Okay I have to check well here Im reading this well the problem is the assignment its just not so clear here it says that the element only accepts son fi name and is initialized as a Stream now that Im looking here I initialized it as a null I initialized it as an empty that could be the problem then lets check to put null here Im going to reload to remove the error and select again well no it wasnt that the other thing is this one that doesnt have to be here then Im going to remove it I think its this Im going to put empty here again because the conflict is that thats when we are what happens is that I think now the bmel has established the name the text but its the conversion there between a file type to a Stream now notice that it didnt work so there you can put null or empty Im going to leave it empty since thats what Im handling there we give a load and I dont even know what it did maybe yes maybe not well here it redirected look then at least it did something lets look here in here the public folder indicates well its in green which means that we have here new Data and we have it that was my image from the electron course then Well here everything worked perfectly remember again the validation we delete the previous image if it exists if it does not exist Then nothing happens we keep we generate the new name here we move the image that we have here in the request we move it to the location that we want in this case it is image post remember that here I used the help function called publish to simply get the path you can print a dd and it will give you the complete or absolute location up to the image post which is what we want here to upload the file here and here we do access the disk for its management understand delete create or whatever we could also use it to create But well but this is the approach that I know through the move function here So this is already external to the upload part while here what we need to use the move function is the path to where you want to move it Well finally we update here the name of the post specifically the image Better said finally here we update the name of the image that we have here in the post the reference and we make a redirection and here there is not much more mystery that is again by not using the B model because Well if inertia works there is not much more to say the approach that they gave it is through an event that is executed precisely and you could see based on the errors when we select a file then we do something based on an event and that something comes being to establish some Data here in the form specifically in the image field and we establish we access what would be the value or the file that we upload and this would be practically everything here important in case you have some problem out there I am going to show you what I have here in the request image so that you have it there for reference I come back Here I am going to select another one over here well selecting the same This is what we have here we have is an illuminate http or fill that is to say exactly the same that we have in basic arabel this does not change This is the object that is received when we pass a file to arabel And this does not change in inertia it remains Exactly the same and that is why we see that over here it is exactly the same syntax that we use in basic arab the only thing that changes here is in the client That obviously here we are using View and it wouldnt be a traditional html form so if you receive a Stream or something like that here youre doing something wrong so having clarified this a little Im going to try to load another image to see if the one we have previously is being deleted based on this rule that we have here since it has tested us So remember that I only have this one Im going to click it here again here at first it was loaded and notice that the previous one disappears and the new one remains which would be the one you can see here Remember that the previous one was an electron reference and this one would already be from flame with flurer So here we complete the load process and we can move on to the next class
- Andrés Cruz
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter