Creating a downloadable csv file from an HTML table via java

If you have a <table> on your website and you’d like users to be able to download the content of that table to a csv file via java, I’ve got you covered. We’ll need HTML, JavaScript, Java, and the jsoup Java HTML parser.

Add a button on your page

<button id="download">Download</button>

Add an empty form to your page that posts to your controller action

<form id="myForm" method="post" action="/csvExport">
  <input id="reportData" type="hidden" name="policyDetails" />
</form>

JavaScript to grab the HTML

document.getElementById('download').onclick = function () {
  let theData = document.getElementById('reportData');
  // this gets the first table on the screen and pulls the HTML, but you can target by id, class, etc
  theData.value = document.getElementsByClassName('table')[0].outerHTML;
  document.getElementById('myForm').submit();
};

Add jsoup to your build file. Use the latest version.

compile 'org.jsoup:jsoup:1.13.1'

Create a java controller

@PostMapping(value = "/csvExport", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<ByteArrayResource> export(@RequestParam("policyDetails") String policyDetails) {
    try {
        String csvText = generateExcel(policyDetails);
        ByteArrayInputStream bais = new ByteArrayInputStream(csvText.getBytes());
        byte[] byteArray = IOUtils.toByteArray(bais);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=cat.csv");
        return ResponseEntity.ok()
                             .headers(headers)
                             .contentLength(byteArray.length)
                             .contentType(MediaType.APPLICATION_OCTET_STREAM)
                             .body(new ByteArrayResource(byteArray));
    } catch (Exception e) {
        // log and redirect user to an error page
    }
}
public String generateExcel(String policyDetails) {
    StringBuilder sb = new StringBuilder();
    try {
        Document doc = Jsoup.parseBodyFragment(policyDetails);
        Elements rows = doc.getElementsByTag("tr");
        // loop through all the tr
        for (Element row : rows) {
            // loop through all the td
            Elements cells = row.getElementsByTag("td");
            for (Element cell : cells) {
                sb.append(cell.text().concat(","));
            }
            // add a line separator
            sb.append("\n");
        }
    } catch (Exception e) {
        e.getStackTrace();
    }
    return sb.toString();
}
Matt Busche's Picture

About Matt Busche

Matt is a developer at Nationwide Insurance and Freelance Consultant. If this article helped you, please consider buying me a book.

Des Moines, IA https://www.matthewbusche.com