In a Spring MVC application, to download a resource, such as a static file, to the browser, we need to make certain changes in the controller method and in the application configuration. This Spring MVC application discusses those changes for enabling the file download functionality. These changes are applicable for a Spring Boot application as well.
- Configure resource handling to serve static files from the
/WEB-INF/files/
directory (or any other directory where files are present). - Use @GetMapping annotation to map the download URL pattern.
- The handler method retrieves the requested file and returns it as a ResponseEntity<Resource>.
1. Spring MVC File Download Controller
Let’s look at an example implementation of a file download controller in a Spring MVC application.
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
public class FileDownloadController {
private final Path fileStorageLocation = Paths.get("src/main/resources/static/files").toAbsolutePath().normalize();
@GetMapping("/download/pdf/{fileName:.+}")
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
try {
Path filePath = fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
} else {
return ResponseEntity.notFound().build();
}
} catch (MalformedURLException ex) {
return ResponseEntity.badRequest().build();
}
}
}
If you want to enable downloads for only authorized users then check the user’s logged-in status first in the method, and then allow to download otherwise redirect him to the login screen.
Do not forget to add the file locations in the resource handler mappings for static files.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.download")
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**")
.addResourceLocations("/WEB-INF/files/");
}
}
2. Demo
Now if you hit the application URL: ‘http://localhost:8080/springmvcexample/download/pdf/sample.pdf‘, you will be able to get the ‘Save As‘ dialog box in your browser like below:

The file is placed inside the folder “src/main/resources/static/files“. You are free to change the path – make sure you change the controller code as well.
3. Prevent Cross-Referencing or Hot Linking
Many times, other websites may cross-reference (or hot link) the files in their websites as direct links. You may not want to allow it. To disallow all download requests, coming from other domains, you can check if the referer header contains your domain name.
Our modified FileDownloadController will send files to the browser, only if the referer header is not null. This will prevent the images from being downloaded directly by typing their URLs in the browser or the request coming from other domains.
@GetMapping("/download/{fileName:.+}")
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
String referer = request.getHeader("Referer");
if (referer == null || !referer.contains("your-authorized-domain.com")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
// Proceed with downloading the file
}
Now if you try to hit the URL from the browser directly, you will get this error:
java.lang.IllegalStateException: Missing header 'referer' of type [java.lang.String]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.raiseMissingHeaderException(HandlerMethodInvoker.java:797)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestHeader(HandlerMethodInvoker.java:566)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:355)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:172)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
Drop me your questions in the comments section.
Happy Learning !!
Comments