El proceso de carga de archivos es fundamental en cualquier sistema hoy en dia, poder subir imágenes para publicaciones, para un avatar, o documentos que formen parte de un ciclo en la aplicación, son procesos rutinarios hoy en día, por lo tanto, ahora conoceremos cómo crear un proceso de upload o carga de archivos empleando Laravel Inertia.
Gracias a estos esqueletos o scaffolding tienen una integración excelente con Laravel, podemos usar practicamente el mismo codigo desde el lado del servidor, es decir, desde Laravel, en el cliente con Vue, tambien podemos usar practicamente lo mismo, pero, al usar peticiones con Inertia, aqui si cambia un poco la cosa como vamos a conocer en detalle a continuación.
El upload de archivos en la web (también conocido como carga de archivos) es una funcionalidad que permite cargar o enviar archivos desde su PC o equipo local en general al servidor web en donde se encuentra la aplicación de Laravel.
Esta funcionalidad es crucial práticamente en cualquier aplicación web en la cual se requiere cargar archivos como imágenes, archivos de audio, documentos de texto, videos, etc. La carga de archivos se puede implementar de diversas formas, como utilizando formularios HTML viene siendo la más clásiica pero, tambien se puede usar peticiones HTTP ya sera directamente o mediante plugins que facilitan la implementación de esta funcionalidad, tales como Dropzone.js o OrugaUI.
Carga de archivos desde Laravel
Al igual que siempre, comencemos creando un disco en la carpeta public, para poder acceder a los mismos:
config/filesystems.php
'public_upload' => [
'driver' => 'local',
'root' => public_path(),
],
Creamos el controlador destinado para realizar el upload, como puedes ver, el proceso es exactamente el mismo que seguiríamos en Laravel básico:
app/Http/Controllers/Dashboard/PostController.php
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");
}
Crear validaciones para indicar el tipo y el peso del archivo máximo:
$request->validate( [ 'image' => 'required|mimes:jpg,jpeg,png,gif|max:10240' ] )
Indicar la carpeta destino, para esto usamos el disco creado anteriormente:
$request->image->move(public_path("image/post"),$filename);
Generamos un nombre para el archivo:
$data['image'] = $filename = time()."." .$request['image']->extension();
Actualizamos la entidad, en este caso, un post:
$post->update($data);
Carga de archivos desde un componente en Vue
Para el componente en Vue, usaremos un botón para dar un click con la función de upload, puedes usar cualquier otro mecanismo ya sea un proceso de uplaod aparte o que forme parte de algun formulario, como vemos en el curso y libro de Laravel Inertia:
<jet-button class="mt-3" @click="upload">Send</jet-button>
También usaremos un campo de tipo archivo para la carga del mismo, lo importante es notar que, para referenciar el archivo usamos:
@input="form.image = $event.target.files[0]"
Esta es la parte fundamental que tienes que tener en cuenta al momento de usar Inertia en vez de cualquier otro proceso, con esto, queda seleccionado el archivo en nuestro v-model:
<jet-input class="w-full" type="file" @input="form.image = $event.target.files[0]" />
Para la función de upload, usamos la función de Inertia post, es importante notar que, para los procesos de carga de archivos en Inertia, solamente podemos usar peticiones de tipo post:
function upload() {
Inertia.post(route("post.upload", form.id), form);
}
Finalmente, el código completo del componente en Vue:
</jet-form-section>
<div class="container">
<div class="card">
<div class="card-body">
<div class="grid grid-cols-2 gap-2">
<div>
<jet-label value="Image" />
<jet-input
class="w-full"
type="file"
@input="form.image = $event.target.files[0]"
/>
<jet-input-error :message="errors.image" />
</div>
<div>
<jet-button class="mt-3" @click="upload">Send</jet-button>
</div>
</div>
</div>
</div>
</div>
setup(props) {
const form = useForm({
// ***
image: "",
});
function submit() {
Inertia.put(route("post.update", form.id), form);
}
function upload() {
Inertia.post(route("post.upload", form.id), form);
}
return { form, submit, upload };
},
Finalmente, creamos la ruta:
routes/web.php
Route::group(['middleware' => [
'auth:sanctum',
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');
});
Si quisieras usar otro tipo de peticiones, puedes hacerlo sin problemas indicando la opción de enviando siempre una petición de tipo POST e indicando con el _method, el método que realmente quieras usar.
- Andrés Cruz
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter