Send an image from the Java backend to Angular or React using REST services

Updated: 2025-02-12

We want to show in our Angular / React application images without making them directly accessible via a public URL.

The images are served by our Java backend.

How to send the image from the backend

We can load the image in the backend and send the content to the client.

Spring Backend

public @ResponseBody Map<String, String> getImage(@PathVariable String id) throws IOException { 
    Resource resource = new ClassPathResource(imagesPath + id); 
    byte[] imageBytes = Files.readAllBytes(resource.getFile().toPath()); 
    return ResponseEntity.ok() 
            .contentType(MediaType.IMAGE_PNG) // Adjust based on your image type 
            .body(imageBytes); 
} 

We use bytes for the answer. In many old codebase we see often the use of Base 64 encoding:

 String encodeImage = Base64.getEncoder() 
        .withoutPadding() 
        .encodeToString(Files.readAllBytes(file.toPath())); 
Map<String, String> jsonMap = new HashMap<>(); 
jsonMap.put("content", encodeImage); 
 
return jsonMap;   

However, Base64 encoding has extra Payload compared to bytes, making it less efficient for large images.

Angular Frontend

console result of the download
This screenshot represents the previous Base64 version.

import { DomSanitizer } from '@angular/platform-browser'; 
import { HttpClient } from '@angular/common/http'; 
import { Component } from '@angular/core'; 
 
@Component({ 
  selector: 'app-image', 
  template: `<img *ngIf="imageUrl" [src]="imageUrl" alt="Image from server">` 
}) 
export class ImageComponent { 
  imageUrl: any; 
 
  constructor(private http: HttpClient, private sanitizer: DomSanitizer) {} 
 
  getImage() { 
    this.http.get('http://localhost:8080/image/image-id', { responseType: 'blob' }) 
      .subscribe(blob => { 
        const objectURL = URL.createObjectURL(blob); 
        this.imageUrl = this.sanitizer.bypassSecurityTrustUrl(objectURL); 
      }); 
  } 
} 

In the Frontend we receive the Blob and bind the content to the <img> tag.

URL.createObjectURL(blob) converts the binary Blob into an object URL in memory, this is used by the browser to visualize the image.

The blob object cannot be assigned to the img.src directly.

Angular's DomSanitizer is used to prevent security warnings (Angular's strict DOM security may block it).

The object will stay in memory until when the page is reloaded and the document unloaded, for this reason it should be removed when is not used anymore:

ngOnDestroy() { 
  if (this.objectURL) { 
    URL.revokeObjectURL(this.objectURL); 
  } 
} 

React Frontend

If you're using React with TypeScript, the process is similar.

import { useState, useEffect } from "react"; 
 
const ImageComponent: React.FC = () => { 
  const [imageUrl, setImageUrl] = useState<string | null>(null); 
 
  useEffect(() => { 
    let objectURL: string | null = null; 
 
    const fetchImage = async () => { 
      try { 
        const response = await fetch("http://localhost:8080/image/image-id"); 
        const blob = await response.blob(); 
        objectURL = URL.createObjectURL(blob); 
        setImageUrl(objectURL); 
      } catch (error) { 
        console.error("Error fetching image:", error); 
      } 
    }; 
 
    fetchImage(); 
 
    return () => { 
      if (objectURL) { 
        URL.revokeObjectURL(objectURL); // Cleanup memory on unmount 
      } 
    }; 
  }, []); 
 
  return <>{imageUrl && <img src={imageUrl} alt="Fetched from backend" />}</>; 
}; 
 
export default ImageComponent; 

useState<string | null> ensures imageUrl is either a string or null (avoids undefined errors).

let objectURL: string | null = null; keeps track of the URL for proper cleanup.


WebApp built by Marco using Java 21 - Hosted in Switzerland