Ad

How To Download XLSX File From A Server Response In Javascript?

I have a react frontend and java server using the Micronaut framework. In the BaseController of my Micronaut Framework, I am creating an XLSX file and then sending the response so that it gets downloaded when called from the frontend code.

BaseController

@Inject ExportService exportService

@Controller('/abc/api/v1')
@Slf4j
class BaseController implements CachingHandler, CommonUtils {
    @Post('/export/{name}')
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.ALL)
    executeExporter(String name, @Nullable @Body LinkedHashMap payload) {
        def handler = { LinkedHashMap paramMap ->
            List paramMapList = paramMap.get("data") as List
            Byte[] resultBytes = exportService.exportToXLSX(paramMapList, getFileName(getLookupValue(name), paramMap.get("key") as String), true)
            log.info String.format("About to return XLSX file %s for %s",getFileName(getLookupValue(name), paramMap.get("key") as String), name)
            return resultBytes
        }
        def results = handler.call(payload)
        InputStream inputStream = new ByteArrayInputStream(results)
        return new StreamedFile(inputStream, getFileName(getLookupValue(name), payload["key"] as String))
    }
}

ExportService

Note: Using the main method of this class I am able to create a TestReport.xlsx file. XLSXExporter class uses Apache POI library to generate XLSX file.

@Prototype
@Slf4j
class ExportService implements CommonUtils {

    Byte[] exportToXLSX(List response, String fileName, boolean isDelete) {
        def headers = []
        try {
            headers = response[0].keySet()
        } catch(Exception e) {
            e.printStackTrace()
        }
        Map params = [:]
        params[Constants.HEADERS] = headers
        params[Constants.DATA] = response

        XLSXExporter xlsxExporter = new XLSXExporter()
        boolean fileCreated = xlsxExporter.writeData(Constants.DEFAULT_SHEET_NAME, fileName, params)
        if (fileCreated) {
            Byte[] workbookContent = xlsxExporter.getFile(fileName, isDelete)
            return workbookContent
        } else {
            return new Byte[0]
        }
    }

    static void main(String[] args) {
        def param = []
        for (int i in 1..5) {
            def paramMap = [:]
            paramMap["key1"] = "data"+i
            paramMap["key2"] = "data"+i
            paramMap["key3"] = "data"+i
            param.add(paramMap)
        }
        ExportService exportService = new ExportService()
        Byte[] resultBytes = exportService.exportToXLSX(param, "TestReport.xlsx", false)

        /**
            I am able to create a proper TestReport.xlsx file using this main method
        **/
    }
}

I tested the above API from Postman and it is able to download an XLSX file. enter image description hereenter image description here

When I call the above export API using my application (javascript), it is able to download an xlsx file but it does not open.

Javascript code to call export API

const exportData = (filteredRows, activity) => {
    let filename = "TestReport.xlsx";
    return axios({
        headers: {
            'Content-type': 'application/json'
         },
        accept:'application/x-www-form-urlencoded',
        url: '/abc/api/v1/export/'+ activity,
        method: 'post',
        data: {
            "key": "8575",
            "type":"userdetails",
            "data":filteredRows
        }
    }).then(resp => {
        var blob = resp.data;
        if(window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, filename);
        }
        else{
            var downloadLink = window.document.createElement('a');
            downloadLink.href = window.URL.createObjectURL(new Blob([blob], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}));
            downloadLink.download = filename;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
           }
    });
}

enter image description hereenter image description here Once I click yes on the above dialog I get below error and nothing gets displayed as opposed to the file downloaded from Postman. enter image description here

Ad

Answer

Your MS Excel (XLSX) file generated on the server and sent back to the client via your API. You can download the response as a file by using responseType = blob. You should also set a filename on your browser to give a name to the downloaded file.

Try below snippet.

const exportData = (filteredRows,activity) => {
    let filename = "TestReport.xlsx";
    let xmlHttpRequest = new XMLHttpRequest();
    xmlHttpRequest.onreadystatechange = function() {
        var a;
        if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {
            a = document.createElement('a');
            a.href = window.URL.createObjectURL(xmlHttpRequest.response);
            a.download = filename;
            a.style.display = 'none';
            document.body.appendChild(a);
            a.click();
        }
    };
    xmlHttpRequest.open("POST", '/abc/api/v1/export/'+ activity);
    xmlHttpRequest.setRequestHeader("Content-Type", "application/json");
    xmlHttpRequest.responseType = 'blob';
    xmlHttpRequest.send(JSON.stringify({
        "key": "8575",
        "type":"userdetails",
        "data":filteredRows
    }));
}
Ad
source: stackoverflow.com
Ad