13

I am using Apache POI to generate .xlsx file.

I would like to return that file from Spring controller. Here's what I've done so far:

Controller:

@RequestMapping(method = RequestMethod.GET)
    public HttpEntity<byte[]> createExcelWithTaskConfigurations(HttpServletResponse response) throws IOException {
        byte[] excelContent = excelService.createExcel();

        HttpHeaders header = new HttpHeaders();
        header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=my_file.xls");
        header.setContentLength(excelContent.length);

        return new HttpEntity<>(excelContent, header);
    }

Is it possible to return actual excel file from rest controller so user can download it to his computer ? As for now controller returning byte[] but I would like to return it actual file. How can I achieve that ?

Martin Čuka
  • 16,134
  • 4
  • 23
  • 49
  • You can use standart apache commons utils to download file. [Similar question.](https://stackoverflow.com/questions/5673260/downloading-a-file-from-spring-controllers) – Igor Konyaev Aug 04 '18 at 10:21
  • Yes, I've already read it. I've tried to return InpurtStream from Service creating excel then used IOUtils.copy(targetStream, response.getOutputStream()); in controller but it only "print" response in unreadable characters. I would like to actually download the file from controller. No luck so far – Martin Čuka Aug 04 '18 at 10:33
  • How about like [that](https://stackoverflow.com/questions/43261106/convert-bytearray-to-xssfworkbook-using-apache-poi)? This question is also very close to yours. – Igor Konyaev Aug 04 '18 at 10:41
  • Have a look at https://stackoverflow.com/a/35683261/4516887 – fateddy Aug 04 '18 at 12:18

4 Answers4

25

You can use ByteArrayResource to download as a file. Below is the modified code snippet of yours

    @GetMapping(value="/downloadTemplate")
    public HttpEntity<ByteArrayResource> createExcelWithTaskConfigurations() throws IOException {
        byte[] excelContent = excelService.createExcel();

        HttpHeaders header = new HttpHeaders();
        header.setContentType(new MediaType("application", "force-download"));
        header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=my_file.xlsx");


        return new HttpEntity<>(new ByteArrayResource(excelContent), header);
    }

If you are trying to generate excel using apache poi, please find the code snippet below

    @GetMapping(value="/downloadTemplate")
    public ResponseEntity<ByteArrayResource> downloadTemplate() throws Exception {
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            XSSFWorkbook workbook = createWorkBook(); // creates the workbook
            HttpHeaders header = new HttpHeaders();
            header.setContentType(new MediaType("application", "force-download"));
            header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ProductTemplate.xlsx");
            workbook.write(stream);
            workbook.close();
            return new ResponseEntity<>(new ByteArrayResource(stream.toByteArray()),
                    header, HttpStatus.CREATED);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
Olivier Depriester
  • 1,615
  • 1
  • 7
  • 20
vettrivel18
  • 366
  • 3
  • 5
  • Thanks for the Excel / POI example, great solution imo as it fits in nicely the with the Spring way of doing things . FYI for anyone using this, by 'fitting in with Spring' I mean it returns Spring's ResponseEntity, and the classes doing the download wok are from org.springframework.core.io and org.springframework.http packages. – MetalRules Apr 14 '20 at 00:14
  • what is XSSFWorkbook workbook = createWorkBook();?? – KevO Jul 02 '21 at 05:07
  • @KevO Its probably a method that creates a new Workbook. Use XSSFWorkbook workbook = new XSSFWorkbook(); instead – Saideep Ullal Aug 24 '22 at 05:04
1

Thanks to @ JAR.JAR.beans. Here is the link: Downloading a file from spring controllers

@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
@ResponseBody 
public FileSystemResource getFile(@PathVariable("file_name") String fileName) {
    return new FileSystemResource(myService.getFileFor(fileName)); 
}
Mafuj Shikder
  • 141
  • 1
  • 8
0

This is working code I have used to download txt file. Same should do for excel file as well.

@GetMapping("model")
public void getDownload(HttpServletResponse response) throws IOException {


    InputStream myStream = your logic....

    // Set the content type and attachment header.  for txt file
    response.addHeader("Content-disposition", "inline;filename=sample.txt");
    response.setContentType("txt/plain");

    // xls file
    response.addHeader("Content-disposition", "attachment;filename=sample.xls");
    response.setContentType("application/octet-stream");

    // Copy the stream to the response's output stream.
    IOUtils.copy(myStream, response.getOutputStream());
    response.flushBuffer();
}
MyTwoCents
  • 7,284
  • 3
  • 24
  • 52
0

Add this lib

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

Put Excel files/folder in src\main\resources

package com.example.controller;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStream;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/download")
public class DownloadController {

    private static final Logger LOGGER = LoggerFactory.getLogger(DownloadController.class);

    // GET http://localhost:80/download/B01-DN_01_Summary.xlsx

    /**
     * Get all accounts belong to a specific tenant.<br/>
     * GET http://localhost/account/all?tenant_id=-32768 .
     *
     * @return
     */
//    @GetMapping("/{file_name}")
//    public @ResponseBody byte[] getImage(@PathVariable("file_name") String file_name) throws IOException
// {
//        LOGGER.info("Call method getAllAccounts() .");
//     InputStream inputStream = getClass().getResourceAsStream("/FilesHere/ImportExcel/" + file_name);
//     return IOUtils.toByteArray(inputStream);
//    }
// E:\github\spring_jwt\src\main\resources\FilesHere\ImportExcel\B01-DN_01_Summary.xlsx
    @GetMapping("/{file_name}")
    public HttpEntity<ByteArrayResource> createExcelWithTaskConfigurations(@PathVariable("file_name") String file_name) throws IOException {
        InputStream inputStream = getClass().getResourceAsStream("/FilesHere/ImportExcel/" + file_name);
        byte[] excelContent = IOUtils.toByteArray(inputStream);
        HttpHeaders header = new HttpHeaders();
        header.setContentType(new MediaType("application", "force-download"));
        header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file_name);
        return new HttpEntity<>(new ByteArrayResource(excelContent), header);
    }

}
Vy Do
  • 46,709
  • 59
  • 215
  • 313