amdev
amdev

Reputation: 3299

Spring - Download excel with POI

I have this controller which create an empty sheet and I want to return the excel file to the navigator. The problem is, the excel file is corrupted.

If I create the file on my computer the file isn't corrupted, so my HSSFWorkbook is valid. Seems a problem of encodage/encapsulation added by the spring context ?

@Controller
public class ExportController {

@RequestMapping(value = "/export/test/excel", method = RequestMethod.POST)
public void downloadExcelTestFile(
        HttpServletRequest request, 
        HttpServletResponse response) throws IOException {

    HSSFWorkbook wb = new HSSFWorkbook();

    wb.createSheet("Sheet1");

    //response.reset();
    //response.setStatus(HttpServletResponse.SC_OK);
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename=test.xls");

    OutputStream out = response.getOutputStream();
    wb.write(out); 

    out.flush();
    out.close();
    wb.close();
}

The download start well, I receive the file test.xls, but I can't open it. Is there a Spring way to achiev a proper download inside a @Controller ?

I use Spring 4.2.4

UPDATE 1

I tried a Spring way but it's not working better

    HSSFWorkbook wb = new HSSFWorkbook();

    wb.createSheet("Sheet1");

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    try {
        wb.write(bos);
    } finally {
        bos.close();
    }

    byte[] bytes = bos.toByteArray();

    HttpHeaders headers = new HttpHeaders();

    headers.set("Content-Type", "application/vnd.ms-excel;");
    headers.set("content-length",Integer.toString(bytes.length));
    headers.set("Content-Disposition", "attachment; filename=test.xls");

    return  new ResponseEntity<byte[]>(bytes, headers, HttpStatus.CREATED);

UPDATE 3

I found a reason but I don't understand why.

If I build my war file and deploy it manually in the very same tomcat 7.0.70 it works. My Excel is not corrupted.

If I download from the dev environnement in eclipse, it doesn't work. Seems a tomcat + eclipse issue.

Upvotes: 2

Views: 13608

Answers (2)

Madan Reddy
Madan Reddy

Reputation: 85

Sample Spring Backed Code to create an excel and return it using Spring REST. The input parameters may change as per your requirement

@RequestMapping(value = "/convertFlatFileToExcel.do", method = RequestMethod.POST)
public HttpEntity<byte[]> convertFlatFileToExcel(@RequestParam(value="file") MultipartFile file,@RequestParam(value="jobid") String jobid) {
        ByteArrayOutputStream archivo = new ByteArrayOutputStream();
        XSSFWorkbook workbook = new XSSFWorkbook();
        workbook.write(archivo);
        if(null!=workbook && null!=archivo) {
            workbook.close();
                        archivo.close();
        }
    byte[] documentContent = archivo.toByteArray();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
    headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"myexcelfile.xls\"");
    headers.setContentLength(documentContent.length);
    response = new ResponseEntity<byte[]>(documentContent, headers, HttpStatus.OK);
}

**Sample UI Code: Below is the sample code to call to Rest Service using Angular JS. Import the FileSaver js file using https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js This will have the method saveAs() to save the given excel blob data with a given name. **

$http.post(urlBase+'/convertFlatFileToExcel.do', formData,{
                transformRequest : angular.identity,
                responseType: 'arraybuffer',
                headers : {
                    'Content-Type' : undefined,
                    'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                }})
                .then(
                    function (response) {
                        $window.sessionStorage.showProgress = "";
                        var file = new Blob([response.data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
                        saveAs(file, jobid.toUpperCase()+'.xlsx');
                    },
                    function (errResponse) {
                        $window.sessionStorage.showProgress = "";
                        $mdDialog.show($mdDialog.alert({title: 'Invalid Job ID!',textContent: 'Please enter a valid Job ID. For any issues, please contact the admin!',ok: 'GOT IT!'}));
                        deferred.reject(errResponse);
                    });

Upvotes: 0

amdev
amdev

Reputation: 3299

Ok that wasn't a Spring issue, not even a tomcat issue.

The problem was from my grunt-connect-proxy, when I run my front throught localhost:9000 : files that I downloaded were corrupted. If I build the project in a war file or run the front from localhost:8080 ( same port than the server ) without "grunt serve" and so without the proxy it works.

I have not fix the problem with grunt ... I just ignore it, but this answer can save your time.

Upvotes: 0

Related Questions