Antes que te vayas
Inscríbete en nuestro curso gratuito de Laravel
Aprende a subir múltiples imágenes en Laravel con solo arrastrar y soltar (drag and drop), usando Dropzone.
En este tutorial aprenderás a programar lo siguiente:
Una zona en la que tus usuarios podrán arrastrar y soltar imágenes.
De hecho, ellos podrán ver una miniatura (thumbnail) de cada imagen que están subiendo, y una barra de progreso por cada una de ellas.
¿Y si simplemente quiero seleccionar y subir varias imágenes?
También se puede.
Con dropzone puedes dar un clic al área correspondiente, y podrás seleccionar las imágenes desde tus archivos.
Dropzone.js es la librería Javascript que vamos a usar para conseguir implementar el área de "drag & drop".
Con la intención que todo el proceso te parezca más claro, he dividido el tutorial en 4 simples pasos:
Para esto tienes 2 opciones:
Si elegiste la primera opción tendrás algo como:
<script src="/js/dropzone.js"></script>
Pero si elegiste la segunda opción:
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.3.0/min/dropzone.min.js"></script>
Muy bien:
Ya tenemos los archivos JavaScript para que dropzone funcione.
Ahora solo nos falta añadir los estilos.
La CDN también nos proporciona una forma de incluir el CSS correspondiente:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.3.0/min/dropzone.min.css">
Para agilizar este paso vamos a partir del ejemplo que aparece en la documentación oficial.
Creamos nuestro formulario:
<form action="/file-upload"
class="dropzone"
id="my-awesome-dropzone">
</form>
E inicializamos dropzone usando JavaScript de esta manera:
Dropzone.options.myAwesomeDropzone = {
paramName: "file", // Las imágenes se van a usar bajo este nombre de parámetro
maxFilesize: 2 // Tamaño máximo en MB
};
En este ejemplo, myAwesomeDropzone
es el id
de nuestro formulario (usando notación camelCase).
Y así es como tenemos nuestro dropzone ya configurado en el lado del cliente.
Sin embargo, hace falta configurar nuestro servidor (backend) para que esté listo para recibir estas imágenes y guardarlas.
¿Qué es lo que tenemos que hacer en este punto?
El código a usar para este propósito va a depender mucho del proyecto que estés desarrollando:
Tus requerimientos van a influir en el modelado de las tablas que vas a necesitar.
A modo de ejemplo, vamos a hacer lo siguiente:
En este caso particular, tenemos 3 modelos:
users
)projects
)project_images
)Para este ejemplo cada proyecto sería equivalente a una galería de imágenes.
Pero lo cierto es que un proyecto puede tener más muchos datos, además de las imágenes.
Repito: todo depende de tus requerimientos específicos.
Nuestro modelo y migración para las imágenes los podemos crear así:
php artisan make:model ProjectImage -m
Entonces en nuestra migración podemos tener:
Schema::create('project_images', function (Blueprint $table) {
$table->increments('id');
$table->integer('project_id')->unsigned();
$table->foreign('project_id')->references('id')->on('projects');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->string('name');
$table->string('description');
$table->string('file_name');
$table->timestamps();
});
Todo esto lo puse para darte una idea más clara del ejemplo que estamos viendo.
Ahora sí entremos en materia.
El atributo action
del formulario es importantísimo, porque allí se define la ruta a la que se harán las peticiones para subir las imágenes.
En el código de ejemplo, tiene el valor de /file-upload
.
Aquí puedes usar la ruta que creas correspondiente.
Para este ejemplo usaremos /proyecto/{id}/imagenes
.
De tal forma que en el parámetro de ruta id
indicaremos el proyecto para el que se subirán las imágenes.
<form action="{{ asset('/proyecto/'.$project->id.'/imagenes') }}"
class="dropzone" id="my-awesome-dropzone">
{{ csrf_field() }}
</form>
No olvidar el CSRF Token. Laravel lo necesita porque se trata de una petición POST.
Y ya está. Ya lo tenemos.
Esta pequeña ruta será procesada por nuestro controlador cuando se trate de una petición POST.
Route::get('/proyecto/{id}/imagenes', '[email protected]');
Route::post('/proyecto/{id}/imagenes', '[email protected]');
Así, en ProjectImageController
tenemos:
public function index($id)
{
$project = Project::find($id);
return view('projects.images.index')->with(compact('project'));
}
public function upload($id, Request $request)
{
//
}
El método upload
es el que hará la magia.
Allí tenemos el $id
del proyecto para el que se está subiendo la imagen.
Y un objeto $request
con información de la imagen subida.
Por lo tanto:
public function upload($id, Request $request)
{
$file = $request->file('file');
$path = public_path() . '/images/projects';
$fileName = uniqid() . $file->getClientOriginalName();
$file->move($path, $fileName);
$projectImage = new ProjectImage();
$projectImage->project_id = $id;
$projectImage->user_id = auth()->user()->id;
$projectImage->file_name = $fileName;
$projectImage->save();
}
Con esto ya debería funcionar todo. Pero, de todas formas ...
Repasemos línea por línea lo que hace el método upload
:
$file
.$path
con la ruta donde queremos guardar nuestras imágenes.$fileName
con el nombre que se usará para guardar la imagen. Aquí se usa uniqid()
para asegurarnos de que el nombre no se repita y ninguna imagen se termine sobreescribiendo.move
(le indicamos dónde guardar y con qué nombre).Laravel y PHP nos facilitan la tarea de subir imágenes.
Como puedes ver en el último snippet de código, lo podemos hacer con muy pocas líneas.
Por otro lado, Dropzone nos permite subir imágenes con una interfaz amigable para el usuario.
Y todo esto se puede configurar rápidamente.
Tal vez el tutorial ha sido un poco extenso por entrar en detalles. Pero si sigues los pasos, verás que realmente es fácil.
Disculpa que vaya por allí con tantos rodeos, pero quiero que sea útil incluso para quienes empiezan a usar Laravel.
Gracias por tu visita, y recuerda compartir si te ha sido de ayuda.
Si te interesa hacer alguna operación sobre las imágenes que suben tus usuarios, como:
Te recomiendo ver el siguiente video:
Generalmente tenemos una sección donde están todas las imágenes subidas, y una segunda sección con el dropzone.
Los usuarios pueden arrastrar y soltar sus imágenes sobre el área donde aplicamos el dropzone.
Estas imágenes se subirán al instante. Pero, no se mostrarán en el listado de imágenes ya subidas.
Si queremos mostrarlas de ese lado, es necesario usar el evento success
de dropzone, para capturar la respuesta que se recibe desde el controlador, luego de una subida exitosa.
Entonces, en nuestro controlador devolvemos la información de la imagen que se acaba de subir, añadiendo una línea al final del método upload
:
public function upload($id, Request $request)
{
$file = $request->file('file');
$path = public_path() . '/images/projects';
$fileName = uniqid() . $file->getClientOriginalName();
$file->move($path, $fileName);
$projectImage = new ProjectImage();
$projectImage->project_id = $id;
$projectImage->user_id = auth()->user()->id;
$projectImage->file_name = $fileName;
$projectImage->save();
return $projectImage;
}
Y en nuestro Javascript capturamos esa respuesta:
Dropzone.options.myAwesomeDropzone = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
success: function (file, response) {
console.log(response);
}
};
Así, obtenemos en la consola algo como lo siguiente:
Aquí lo que nos interesa es principalmente el atributo file_name
, ya que con este dato podemos renderizar la imagen que se acaba subir.
Pero he devuelto toda la información para que veas que se puede capturar la respuesta del servidor.
Comparte este post si te fue de ayuda 🙂.
Cualquier duda y/o sugerencia es bienvenida.
Regístrate
Inicia sesión para acceder a nuestros cursos y llevar un control de tu progreso.
Cursos recomendados
Aprende Laravel desde cero y desarrolla aplicaciones web reales, en tiempo récord, de la mano de Laravel.
Ingresar al cursoActualiza tus proyectos desde cualquier versión hasta la última versión estable de Laravel.
Ingresar al cursoDesarrollemos un Messenger! Aprende sobre Channels, Queues, Vuex, JWT, Sesiones, BootstrapVue y mucho más.
Ingresar al cursoInscríbete en nuestro curso gratuito de Laravel