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.
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);
}
});
}
Once I click yes on the above dialog I get below error and nothing gets displayed as opposed to the file downloaded from Postman.
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
}));
}