I have a java/spring boot application where I want to build an API endpoint that creates and returns a downloadable excel file. Here is my controller endpoint:
@RestController
@RequestMapping("/Foo")
public class FooController {
    private final FooService fooService;
    @GetMapping("/export")
    public ResponseEntity export() {
        Resource responseFile = fooService.export();
        return ResponseEntity.ok()
                             .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+responseFile.getFilename())
                             .contentType(MediaType.MULTIPART_FORM_DATA)
                             .body(responseFile);
    }
}
Then the service class
public class FooService {
  public Resource export() throws IOException {
    StringBuilder filename = new StringBuilder("Foo Export").append(" - ")
                                                            .append("Test 1.xlsx");
    return export(filename);
  }
  private ByteArrayResource export(String filename) throws IOException {
      byte[] bytes = new byte[1024];
      try (Workbook workbook = generateExcel()) {
          FileOutputStream fos = write(workbook, filename);
          fos.write(bytes);
          fos.flush();
          fos.close();
      }
      return new ByteArrayResource(bytes);
  }
  private Workbook generateExcel() {
      Workbook workbook = new XSSFWorkbook();
      Sheet sheet = workbook.createSheet();
      //create columns and rows
      return workbook;
  }
  private FileOutputStream write(final Workbook workbook, final String filename) throws IOException {
      FileOutputStream fos = new FileOutputStream(filename);
      workbook.write(fos);
      fos.close();
      return fos;
  }  
}
This code successfully creates the proper excel file using the Apache POI library. But this won't return it out of the controller properly because ByteArrayResource::getFilename always returns null:
/**
 * This implementation always returns {@code null},
 * assuming that this resource type does not have a filename.
 */
@Override
public String getFilename() {
    return null;
}
What type of resource can I use to return the generated excel file?
Since you are using ByteArrayResource, you can use the below controller code assuming that the FooService is autowired in the controller class.
@RequestMapping(path = "/download_excel", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String fileName) throws IOException {
ByteArrayResource resource = fooService.export(fileName);
return ResponseEntity.ok()
        .headers(headers) // add headers if any
        .contentLength(resource.contentLength())
        .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
        .body(resource);
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With