Tuesday, January 26, 2021

Spring MVC File Download Example

In this post we’ll see a Spring MVC application to download a file (image, pdf, zip etc.) from web server.

Spring MVC file download example – Technologies used

Following is the list of tools used for the Spring MVC file download example.

  1. Spring 5.0.8 Release (Spring core, spring web, spring webmvc).
  2. Java 10
  3. Tomcat server V 9.0.10
  4. Eclipse Photon 4.8.0 for Java EE development.

Spring MVC file download example project structure using Maven

Options in Spring MVC for file download

  • In your Spring MVC application for file download you can use HttpServletResponse to write the downloaded file to the output stream of the servlet response. If you are using this option then you need to do the following.
    1. Pass HttpServletResponse as a parameter to your controller handler method and the method's return type is void.
    2. Find MIME type of the content of downloaded file and set it to the response's content type. If you are not able to detect the mime type set it to application/octet-stream. Mime type can be any of these- application/pdf, application/xml, image/png, image/jpeg etc.
    3. In response set a Content-Disposition header- response.setHeader(“Content-Disposition”, “attachment; filename=” + fileName); Where fileName is the name of the file to be downloaded.
    4. Copy the file bytes to the OutputStream of response.
  • You can return the file from the controller handler method as a FileSystemResource wrapped with in ResponseEntity i.e. ResponseEntity<FileSystemResource>. If you are using this option then you need to do the following.
    1. Return type of the controller handler method is ResponseEntity<FileSystemResource>.
    2. Find MIME type of the content of downloaded file and set it to the response's header. If you are not able to detect the mime type set it to application/octet-stream. Mime type can be any of these- application/pdf, application/xml, image/png, image/jpeg etc.
    3. In response set a Content-Disposition header- response.setHeader(“Content-Disposition”, “attachment; filename=” + fileName); Where fileName is the name of the file to be downloaded.
    4. Set the response status code as OK.
    5. Set the content of the file as response entity body.

Spring MVC file download example – View

In the JSP there are two links for downloading two files.

download.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<body>
  <a href='<s:url value="/downloadFileUsingResponse/Rules.pdf"></s:url>'>Download Rules.pdf</a><br/>
  <a href='<s:url value="/downloadFileUsingEntity/Test.png"></s:url>'>Download Test.png</a>
</body>
</body>
</html>

As you can see Spring tags library is used here for creating the URL. For that you need to add the following line in your JSP.

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>

After the application is deployed the JSP page can be accessed using the URL- http://localhost:8080/spring-mvc/download

Here spring-mvc is the name of the Spring MVC application.

Spring MVC file download

Spring MVC file download example – Controller Class

@Controller
public class DownloadController {
  @RequestMapping(value = "/download", method = RequestMethod.GET)
  public String showDownload(Model model) {    
    return "download";
  }
    
  @RequestMapping(value = "/downloadFileUsingResponse/{fileName:.+}")
  public void downloadFileAsResponse(HttpServletRequest request, 
    HttpServletResponse response, @PathVariable("fileName") String fileName) {
    try {
      // getting the path to file 
      String dir = request.getServletContext().getRealPath("/WEB-INF/resources/");            
      Path file = Paths.get(dir, fileName);
      if(!Files.exists(file)){
        String errorMessage = "File you are trying to download does 
          not exist on the server.";            
        OutputStream outputStream = response.getOutputStream();
        outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8")));
        outputStream.close();
        return;
      }
      // getting mimetype from context
      String mimeType= request.getServletContext().getMimeType(
        file.getFileName().toString());
      if(mimeType == null){
        // Not able to detect mimetype taking default
        mimeType = "application/octet-stream";
      }
      response.setContentType(mimeType);
      response.addHeader("Content-Disposition", "attachment; filename="+fileName);        
      Files.copy(file, response.getOutputStream());
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
    
  @RequestMapping(value = "/downloadFileUsingEntity/{fileName:.+}")
  public ResponseEntity<FileSystemResource> downloadFileAsEntity(
      HttpServletRequest request, @PathVariable("fileName") String fileName) {
    
    String dir = request.getServletContext().getRealPath("/WEB-INF/resources/");
    
    Path file = Paths.get(dir, fileName);
    FileSystemResource fileResource = new FileSystemResource(file.toFile());
    if(!Files.exists(file)){                     
      return ResponseEntity.notFound().build();
    }
    // getting mimetype from context
    String mimeType= request.getServletContext().getMimeType(
      file.getFileName().toString());
    if(mimeType==null){
      // Not able to detect mimetype taking default
      mimeType = "application/octet-stream";
    }
    return ResponseEntity.ok()
    .header("Content-Disposition", "attachment; filename="+fileName)
    .contentType(MediaType.valueOf(mimeType)).body(fileResource);
  }
}
  • There are two methods in the controller class for handling download requests. First method downloadFileAsResponse() uses the HttpServletResponse to write the downloaded file to the output stream of the servlet response.
    Second method downloadFileAsEntity() uses the option where FileSystemResource is wrapped with in ResponseEntity and that is returned from the method.
  • File name is passed as a parameter with in the request path and @PathVariable annotation is used to retrieve the parameter from the request path.
  • In case you are wondering why path given along with @RequestMapping has a regular expression .+ in it, please refer this post- Spring MVC Dot (.) Truncation Problem With @PathVariable Annotation
  • Path where files are kept is WEB-INF/resources, in the controller methods file is read from that location. You can change it to some other location, read it through a property file or give an absolute path as per your requirement.
  • In the methods, mime type is detected from the file name. Mime type “application/octet-stream” is used as default.

That's all for this topic Spring MVC File Download Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Web MVC Tutorial
  2. Spring MVC @RequestParam Annotation Example
  3. Connection Pooling Using C3P0 Spring Example
  4. Spring Transaction Management Example - @Transactional Annotation and JDBC
  5. How to Read Properties File in Spring Framework

You may also like-

  1. Spring Profiles With Examples
  2. Spring Expression Language (SpEL) With Examples
  3. Difference Between component-scan And annotation-config in Spring
  4. Bean Scopes in Spring With Examples
  5. ConcurrentHashMap in Java With Examples
  6. Race Condition in Java Multi-Threading
  7. Type Casting in Java With Conversion Examples
  8. How to Create Password Protected Zip File in Java

No comments:

Post a Comment