Approach 1: Programmatic File Streaming via Controller
When image are stored outside the web root or require access control, streaming the file through a dedicated endpoint is the standard approach. The frontend requests the image via a query parameter, and the backend reads the file from disk and pipes it directly to the HTTP response.
Frontend Implementation
<img :src="`/api/media/stream?identifier=${record.fileName}`" alt="Server Image" />
Backend Implementation
@RestController
@RequestMapping("/api/media")
public class MediaDeliveryController {
private static final String UPLOAD_DIRECTORY = "/var/application/storage/";
@GetMapping("/stream")
public void deliverImage(@RequestParam String identifier, HttpServletResponse response) {
File sourceFile = new File(UPLOAD_DIRECTORY, identifier);
if (!sourceFile.exists() || !sourceFile.isFile()) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
try (InputStream fileStream = new FileInputStream(sourceFile);
OutputStream clientStream = response.getOutputStream()) {
response.setContentType("image/jpeg");
response.setHeader("Content-Disposition", "inline");
byte[] buffer = new byte[2048];
int bytesRead;
while ((bytesRead = fileStream.read(buffer)) != -1) {
clientStream.write(buffer, 0, bytesRead);
}
clientStream.flush();
} catch (IOException ex) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
This method bypasses direct URL exposure but requires an active request for each image load.
Approach 2: Direct Access via Static Resource Mapping
To enable direct HTTP/HTTPS access without routing through a controller, Spring Boot can be configured to map a URL pattern to a physical directory on the server. This allows the web server to handle the file delivery natively.
Configuration Class
@Configuration
public class StaticAssetConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/public-assets/**")
.addResourceLocations("file:/opt/server/uploads/")
.setCachePeriod(86400);
}
}
Once the mapping is active, any file placed in /opt/server/uploads/ becomes accessible via the /public-assets/ URL prefix. The frontend can bind the complete URL directly to the image source.
Frontend Usage
<img src="https://app.example.com/public-assets/profile_88291.jpg"
class="thumbnail"
@click="openPreview" />
This strategy reduces backend overhead by delegating file serving to the embedded web container and enables standard browser caching mechenisms.