Introduction

In this guide we'll discuss how to create and download CSV via REST in Spring Boot. CSV or comma-separated values file is a plain text file. It represents a tabular structure in a very simple way - fields are separated with commas, and rows are separated with a new line. CSV is a widely used format in the software industry because information about data structure doesn't add much size to a file - that is not a case with, for example, xls/xlsx.

There are few ways to generate this file from your objects and pass it as a response from your REST service. In this tutorial, we'll show you how to generate CSV file from the User object and write it directly to the response object. CSV file will be created using Apache commons CSV library, which is just one of many ways to do this (you can for example try with openCSV). 

Dependencies

Add apache commons CSV depencency in your pom.xml if you already don't have it.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.5</version>
</dependency>

How to download CSV via REST in Spring Boot

This controller class is there just to show you needed annotations - as method input you should provide @Context HttpServletResponse and in the service class, we'll be writing directly to it.

import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.example.UserService;

@RestController
@RequestMapping("/api")
public class UserController {

  @Autowired
  UserService userService;

	
  @GetMapping("/users-csv")
  public void downloadUsersCSV(@Context HttpServletResponse httpServletResponse){
    userService.generateCSVResponse(httpServletResponse);
  }

Your service method should also have HttpServletResponse from javax.servlet.http lib as input parameter. We'll get and use writer from it.

import javax.servlet.http.HttpServletResponse;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import org.springframework.http.HttpHeaders;

@Service
public class UserExporter {

@Autowired
UserRepository userRepository;

public void generateCsvResponse(HttpServletResponse response) {

   String filename = "someFileName.csv";
   List<User> = userRepository.findAll();
   try {
      response.setContentType("text/csv");
      response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
               "attachment; filename=\"" + filename + "\"");
      CSVPrinter csvPrinter = new CSVPrinter(response.getWriter(),
      CSVFormat.DEFAULT.withHeader("field1", "field2", "field3"));
      for (OrganisationInvitation user : users) {
        csvPrinter.printRecord(Arrays.asList(user.getField1(), user.getField2(), user.getField3()));
      }
    
      } catch (IOException e) {
        e.printStackTrace();
       } finally {
          if(csvPrinter != null)
            csvPrinter.close();
                 }
        }
  }

In the end, don't forget to close csvPrinter - this way you'll close the stream, flushing it first. It's good practice to close it in finally block so that it doesn't stay open in case of error.