Im doing the frontend and backend of an it shop, to save the images of every product i have a blob column in the product table (dont know if its the best option but dont know another one better), the boss tell me to do an external app to add the an image to every product directly to the db.
private void addImage() {
String selected = tableView.getSelectionModel().getSelectedItem().getDescripcion();
System.out.println("Intentando añadir imagen al artículo: " + selected);
if (selected == null) {
showAlert("Error", "Seleccione un artículo primero para añadir una imagen.");
return;
}
try {
PreparedStatement pstmt = connection.prepareStatement("SELECT Imagen FROM articulos WHERE Descripción = ?");
pstmt.setString(1, selected);
ResultSet rs = pstmt.executeQuery();
if (rs.next() && rs.getString("Imagen") != null) {
showAlert("Error", "El artículo ya tiene una imagen. Use el botón 'Actualizar' para cambiarla.");
return;
}
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("Images", "*.png", "*.jpg", "*.jpeg")
);
File file = fileChooser.showOpenDialog(null);
if (file != null) {
String base64Image = convertImageToBytes(file);
if (base64Image != null) {
pstmt = connection.prepareStatement("UPDATE articulos SET Imagen = ? WHERE Descripción = ?");
pstmt.setString(1, base64Image);
pstmt.setString(2, selected);
pstmt.executeUpdate();
System.out.println("Imagen añadida correctamente al artículo: " + selected);
displayImage(selected);
} else {
showAlert("Error", "Error al convertir la imagen");
}
}
} catch (SQLException e) {
System.out.println("Error al añadir imagen: " + e.getMessage());
showAlert("Error", "Error al añadir imagen: " + e.getMessage());
}
}
private String convertImageToBytes(File imageFile){
byte[] imageBytes = null;
try(ByteArrayOutputStream baos = new ByteArrayOutputStream(); FileInputStream fis = new FileInputStream(imageFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
imageBytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
In the app u just select a product from the db an select an img from your pc, here i dont have a problem the image saves succesfully and even shows itself if u click in the same product again, in the springboot controller i get the product with his image:
@GetMapping("/ofertas")
public ResponseEntity<List<ArticuloDTO>> getArticulosEnOferta() {
List<Articulo> articulos = ArticuloService.obtenerArticulosEnOferta();
List<ArticuloDTO> articulosDTO = articulos.stream().map(a -> new ArticuloDTO(
a.getId_articulo(),
a.getNombre(),
a.getPrecio_medio(),
a.isRebajado(),
a.getPrecioRebajado(),
a.getImagen() != null ? Base64.getEncoder().encodeToString(a.getImagen()) : null
)).collect(Collectors.toList());
return ResponseEntity.ok(articulosDTO);
}
but when i try to show that pic in angular i get an error, normally a loop where the page try to process the image all the time getting a lot of errors in the console log every second.i added some logs to see if i get the blob column from the db, and yes i get it so the problem should be when angular try to process the img.
cargarProductosEnOferta() {
this.isLoading = true;
this.error = null;
this.productService.getProductosEnOferta().subscribe({
next: (productos) => {
console.log('Productos cargados:', productos.length);
this.productosEnOferta = productos;
productos.forEach((producto, index) => {
console.log(`Producto ${index + 1}:`, {
id: producto.id_articulo,
nombre: producto.nombre,
descripcion: producto.descripcion,
precio_medio: producto.precio_medio,
rebajado: producto.rebajado,
precioRebajado: producto.precioRebajado,
imagen: producto.imagen ? {
tipo: typeof producto.imagen,
longitud: producto.imagen.length,
muestra: typeof producto.imagen === 'string'
? producto.imagen.substring(0, 50) + '...'
: 'byte array'
} : 'sin imagen'
});
});
if (productos.length > 0) {
console.log('Estructura completa del primer producto:', JSON.stringify(productos[0], null, 2));
}
this.isLoading = false;
},
error: (error) => {
console.error('Error loading products:', error);
this.error = 'Error al cargar los productos';
this.isLoading = false;
}
});
}
sanitizeBase64Image(imageData: string): SafeUrl {
if (!imageData) {
return this.sanitizer.bypassSecurityTrustUrl('assets/default-product.jpg');
}
try {
return this.sanitizer.bypassSecurityTrustUrl(imageData);
} catch (error) {
console.error('Error processing image:', error);
return this.sanitizer.bypassSecurityTrustUrl('assets/default-product.jpg');
}
}
<div class="ofertas-gallery" *ngIf="!isLoading && !error"
[style.gridTemplateColumns]="'repeat(' + calcularColumnas(productosEnOferta.length) + ', 1fr)'">
<div class="oferta-card" *ngFor="let producto of productosEnOferta">
<div class="oferta-imagen">
<img [src]="sanitizeBase64Image(producto.imagen)"
[alt]="producto.nombre"
class="product-image">
<div class="oferta-badge" *ngIf="producto.rebajado">
-{{calcularPorcentajeDescuento(producto)}}%
</div>
</div>
<div class="oferta-info">
<h3>{{producto.nombre}}</h3>
<div class="oferta-precios">
<span class="precio-original">{{producto.precio_medio}}€</span>
<span class="precio-oferta" *ngIf="producto.rebajado">
{{producto.precioRebajado}}€
</span>
</div>
<button class="btn-agregar-carrito" (click)="agregarAlCarrito(producto)">
<i class="fas fa-shopping-cart"></i>
Añadir al carrito
</button>
</div>
</div>
</div>
Probably im just blind and the error is obviously but i really dont see it xd.
Added some logs to see if i get correctly the img from the db this is an example of a product i get: Estructura completa del primer producto: {
“id_articulo”: 1, //id from the product
“nombre”: “ADAPTADOR USB WIFFI 1200 MBPS NAN0”, // name of the product
“precio_medio”: 12.86, //Price
“rebajado”: true, //In sale
“precioRebajado”: 10, //Sale price
“imagen”: “data:image/jpeg;base64,LzlqLzRBQVFTa1pKUmdBQkFRQUFBUUFCQUFELzJ3QkRBQU1DQWdJQ0FnTUNBZ0lEQXdNREJBWUVCQVFFQkFnR0JnVUdDUWdLQ2drSUNRa0tEQThNQ2dzT0N3a0pEUkVORGc4UUVCRVFDZ3dTRXhJUUV3OFFFQkQvMndCREFRTURBd1FEQkFnRUJBZ1FDd2tMRUJBUUVCQVFFQkFRRUJB……… //The img chain,and yes its longer than this if anyone ask it