Almacenar imágenes en MySQL con JFileChooser
Para almacenar imágenes en una
base de datos existen varias formas, desde almacenar la imagen directamente en
la BD en un cambo BLOOB o almacenar
solo el nombre de la imagen, además de copiarla a una carpeta donde se
almacenen todas las imágenes.
En este ejemplo se utilizara un JFileChooser para elegir la imagen a
guardar, para posteriormente cuando el usuario guarde el registro la aplicación
copiara la imagen a una carpeta predeterminada llamada imágenes y en la base de
datos solo almacenara el nombre de la imagen para su posterior visualización.
1.- Para este ejemplo se crea un
nuevo proyecto llamado imagenesBD, y
posteriormente se crean dos packages
uno llamado clases donde se almacena el programa escrito en java y otro package llamado images donde se copiaran las imágenes que el usuario almacene en la
BD.
Además se agrega la librería MySQL JDBC Driver para la conexión con MySQL.
La estructura del proyecto queda
como en la siguiente imagen.
2.- Para este ejemplo se crea la
base de datos imagenes, donde se crear
la tabla productos, que permite almacenar el nombre de un producto y su imagen,
teniendo como llave principal el idProducto,
adicionalmente se insertan a la tabla un par de registros, téngase en cuenta que
las imágenes también se deben de copiar a la carpeta images, que fue creado anteriormente.
CREATE DATABASE IF NOT
EXISTS `imagenes` DEFAULT CHARACTER SET latin1 COLLATE latin1_spanish_ci;
USE `imagenes`;
--
-- Estructura de tabla
para la tabla `productos`
--
CREATE TABLE IF NOT EXISTS
`productos` (
`idProducto` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(100) COLLATE
latin1_spanish_ci NOT NULL,
`imagen` varchar(100) COLLATE
latin1_spanish_ci NOT NULL,
PRIMARY KEY (`idProducto`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci
AUTO_INCREMENT=1;
--
-- Volcado de datos para
la tabla `productos`
--
INSERT INTO `productos`
(`idProducto`, `nombre`, `imagen`) VALUES
(1, 'sol', 'sol.png'),
(2, 'luna', 'luna.png');
3.- El siguiente paso es diseñar
una interfaz gráfica como la siguiente, donde se tienen controles básicos para
desplazarse por los registros de la base de datos, además de contener la opción
para nuevo donde se habilitara un botón para navegar por los directorios y así
poder seleccionar la imagen deseada, para este ejemplo se filtraran las imágenes
para mostrar solo .png y .jpg las imágenes se visualizaran en un
JLabel.
4.- En el panel de Navegación de
componentes se hace clic con el botón derecho en Other Components, posteriormente en Add From Palette + Swing Windows + File Chooser, de esta forma se
insertar el JFileChooser al proyecto
y permitirá mostrar y utilizar el cuadro de dialogo Abrir.
5.- Una vez insertados los
componentes quedara una estructura como la siguiente, donde ya se han
renombrado cada uno de los componentes insertados.
6.- En la clase principal se
insertan las siguientes librerías que permiten realizar la conexión con la BD,
mostrar el cuadro de dialogo abrir y copiar archivos dentro de las carpetas.
//librería para el manejo de archivos
import java.io.File;
import java.io.IOException;
//librerías para copiar archivos
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
//librerías para conexión con la base de datos
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//librería para almacenar temporalmente una imagen
import javax.swing.ImageIcon;
//librería para mostrar el cuadro de dialogo abrir
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
//librería para mostrar mensajes
import javax.swing.JOptionPane;
7.- Dentro de la clase principal se declaran las
siguientes variables miembros, que permiten realizar la conexión y almacenar la
ruta y el nombre del archivo seleccionado.
private Connection co;
private ResultSet rs;
private Statement st;
private String nombreArchivo;
private String ruta;
private String nuevaRuta;
private File archivo;
8.- El método conectar realiza la conexión con la
BD imágenes, y selecciona los productos dados de alta, además de seleccionar el
primer registro y mostrarlo en los componentes correspondientes.
private void conectar() {
try {
co = DriverManager.getConnection("jdbc:mysql://localhost/imagenes",
"root", "");
st =
co.createStatement();
rs =
st.executeQuery("Select * from productos");
rs.next();
llenarCampos();
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null,
"Error 0:" + err.getMessage());
}
}
9.- Este método muestra el primer registro.
public void primero() {
try {
rs.first();
llenarCampos();
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null, "Error 1:" +
err.getMessage());
}
}
10.- Este método muestra el último registro.
public void ultimo() {
try {
rs.last();
llenarCampos();
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null, "Error 2:" +
err.getMessage());
}
}
11.- Va recorriendo hacia atrás los registros.
public void anterior() {
try {
if (!rs.isFirst()) {
rs.previous();
llenarCampos();
}
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null,
"Error 3:" + err.getMessage());
}
}
12.- Va recorriendo hacia adelante los registros.
public void siguiente() {
try {
if (!rs.isLast()) {
rs.next();
llenarCampos();
}
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null, "Error 4:" +
err.getMessage());
}
}
13.- Inserta un nuevo registro y muestra el registro
insertado.
public void guardar() {
try {
String sql =
"insert into productos(nombre,imagen) values ('" + this.jtfProducto.getText()
+ "','" + nombreArchivo + "');";
st.executeUpdate(sql);
JOptionPane.showMessageDialog(this, "Producto guardado");
rs =
st.executeQuery("Select * from productos");
ultimo();
} catch (SQLException
err) {
JOptionPane.showMessageDialog(null, "Error 5:" +
err.getMessage());
}
}
14.- Este método toma los datos almacenados en el RecordSet (rs) y los muestra en los JLabel y JTextField correspondientes.
public void llenarCampos() {
try {
this.jlidProducto.setText(rs.getString("idProducto"));
this.jtfProducto.setText(rs.getString("nombre"));
this.jlNImagen.setText(rs.getString("imagen"));
this.jlimagen.setIcon(new
javax.swing.ImageIcon(getClass().getResource("/images/" +
rs.getString("imagen"))));
} catch (SQLException err) {
JOptionPane.showMessageDialog(null, "Error 6:" +
err.getMessage());
} catch
(NullPointerException err) {
JOptionPane.showMessageDialog(null, "Error 7:" +
err.getMessage());
}
}
15.- Con el siguiente método se protegen los datos,
ya que al habilitar la opción de Nuevo,
todos los botones para desplazarse se deshabilitan de tal modo que el usuario
no pueda cambiar de registro accidentalmente.
public void bloquearDesbloquear(boolean todos) {
this.jbAnterior.setEnabled(todos);
this.jbSiguiente.setEnabled(todos);
this.jbPrimero.setEnabled(todos);
this.jbUltimo.setEnabled(todos);
this.jbNuevo.setEnabled(todos);
this.jbCargarImagen.setEnabled(!todos);
this.jbGuardar.setEnabled(!todos);
}
16.- En los eventos ActionPerformed de los botones de desplazamiento (jbPrimero, jbAnterior, jbSiguiente,
jbUltimo) se manda llamar a los métodos
correspondientes para el desplazamiento y visualización de los registros.
private void
jbPrimeroActionPerformed(java.awt.event.ActionEvent evt) {
this.primero();
}
private void
jbAnteriorActionPerformed(java.awt.event.ActionEvent evt) {
this.anterior();
}
private void
jbSiguienteActionPerformed(java.awt.event.ActionEvent evt) {
this.siguiente();
}
private void
jbUltimoActionPerformed(java.awt.event.ActionEvent evt) {
this.ultimo();
}
17.- Este método establece un filtro para que únicamente
se muestren las imágenes con extensión PNG y JPG, al abrir el cuadro de dialogo
Abrir, si el usuario presiona el botón Abrir el método almacena el nombre de la
imagen, la ubicación actual, para posteriormente mostrar el jlImagen la imagen seleccionada.
public void cargarImagen(){
try {
ImageIcon imagen;
//permite almacenar la imagen que se abre con el JFileChooser
FileNameExtensionFilter filtro = new FileNameExtensionFilter("PNG,JPG",
"png","jpg");
jfcAbrirArchivo.setFileFilter(filtro);
int abrir =
jfcAbrirArchivo.showOpenDialog(this);
if (abrir ==
JFileChooser.APPROVE_OPTION) {
archivo =
jfcAbrirArchivo.getSelectedFile();
ruta =
archivo.getAbsolutePath();
nombreArchivo =
archivo.getName();
nuevaRuta =
System.getProperty("user.dir") + "\\src\\images\\" +
nombreArchivo;
imagen = new
ImageIcon(ruta);
this.jlNImagen.setText(nombreArchivo);
this.jlimagen.setIcon(imagen);
}
} catch
(NullPointerException err) {
JOptionPane.showMessageDialog(null, "Error 8:" +
err.getMessage());
}
}
18.- El evento ActionPerformed del jbCargarImagen llama al método cargarImagen().
private void
jbCargarImagenActionPerformed(java.awt.event.ActionEvent evt) {
cargarImagen();
}
19.- El evento ActionPerformed del jbNuevo borra el texto de jtfProdocto y
jlNImagen, para que el usuario pueda dar nombre al nuevo producto, además
bloquea los botones de desplazamiento y activa el botón para buscar la imagen y
guardarla.
private void
jbNuevoActionPerformed(java.awt.event.ActionEvent evt) {
this.jtfProducto.setText("");
this.jlNImagen.setText("");
bloquearDesbloquear(false);
}
20.- El evento ActionPerformed del jbGuardar guarda el nuevo registro, además
de copiar la imagen desde la ruta original a la carpeta images del proyecto, para tener todas las imágenes en el mismo
lugar, y deshabilita los botones de búsqueda y guardar, y vuelve a habilitar
los botones de navegación.
private void
jbGuardarActionPerformed(java.awt.event.ActionEvent evt) {
guardar();
copiarArchivo(ruta,
nuevaRuta);
bloquearDesbloquear(true);
}
21.- Este método permite copiar
cualquier archivo desde la ruta origen hasta la ruta destino.
public static void
copiarArchivo(String origen, String destino) {
try {
Path rutaOrigen =
Paths.get(origen);
Path rutaDestino =
Paths.get(destino);
CopyOption[] opciones
= new CopyOption[]{
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES
};
Files.copy(rutaOrigen, rutaDestino, opciones);
} catch (IOException err)
{
JOptionPane.showMessageDialog(null, "Error 9:" +
err.getMessage());
}
}
22.- En la siguiente imagen se
muestra el proyecto cuando se ejecuta, mostrando el nombre del producto y la
imagen que esta almacenada en la carpeta images.
23.- Al hacer clic en el botón nuevo se habilita
la caja para escribir el nombre y el botón para abrir el cuadro de dialogo
Abrir.
24.- Al hacer clic en el botón buscar
(…) se muestra el cuadro de dialogo abrir, que permite navegar por las carpetas
del sistema y seleccionar un archivo de extensión jpg o png.
Comentarios