/blog/*

Download Generate PDF di Spring

Ada kondisi dimana kita perlu membuat katakanlah suatu report berupa file PDF secara on the fly berdasarkan input dari database. Untuk handle kebutuhan ini, kita bisa menggunakan suatu library bernama iTextPDF. Library ini memiliki fitur keren dimana bisa menkonversi template HTML beserta styling-nya menjadi file PDF.

Template Engine Thymeleaf

Pertama-tama siapkan terlebih dahulu layout yang nanti akan dikonversi ke PDF, untuk hal ini kita bisa menggunakan bantuan Thymeleaf yang dimana library ini sudah sangat terintegrasi dengan Spring. Dengan bantuan Thymeleaf, kita bisa passing parameter secara dinamis pada suatu template HTML yang bersifat static. Berikut caranya.

Buat file report.html dan tambahkan xmlns:th="http://www.thymeleaf.org" sebagai XML namespace dari Thymeleaf. Simpan di direktori ./resources/templates.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        ...
        <link th:href="@{css/styles.css}" rel="stylesheet"/>
    </head>
    <body>
        ...
        <div class="content">
            <h1 th:text="'#' + ${name}">#</h1>
            <p>
                Now you know how to generate PDF file and create API to download it in Spring. Nice work!
            </p>
        </div>
    </body>
</html>

Pada potongan kode HTML diatas terdapat suatu parameter ${name} yang bisa kita isikan nilainya secara dinamis dari Java. Berikut caranya:

public byte[] generateReport(String name) throws IOException {

    // passing parameter
    Context context = new Context();
    context.setVariable("name", name);

    String processedHtml = templateEngine.process("report", context);

    ...

}

iTextPDF

Jika template file sudah siap, selanjutnya adalah menjalankan library iTextPDF untuk menkonversi hasil proses dari library Thymeleaf yang berupa String menjadi byte[] yang berisikan hasil file PDF.

public byte[] generateReport(String name) throws IOException {

    // passing parameter
    Context context = new Context();
    context.setVariable("name", name);

    String processedHtml = templateEngine.process("report", context);

    ConverterProperties converterProperties = new ConverterProperties();
    converterProperties.setBaseUri("http://localhost:8080");

    HtmlConverter.convertToPdf(processedHtml, stream, converterProperties);

    byte[] bytes = stream.toByteArray();
    stream.flush();

    return bytes;

}

Jika pada file template terdapat eksternal resource seperti file CSS atau image, kita harus memberitahu base URI kita agar iTextPDF tahu lokasi resource tersebut dengan cara mengisi membuat object dari clas ConverterProperties dan mengisi parameter pada method setBaseUri().

Rest API Download

Terakhir adalah menyiapkan suatu Rest API untuk mengakses "fitur generate report" yang sudah kita buat sebelumnya. Disini kita akan menggunakan module spring-web dari Spring. Berikut caranya:

@Controller
public class WebController {

    @Autowired
    private ReportService reportService;

    @GetMapping("/report")
    public ResponseEntity<?> getReport() throws IOException {

        String name = "Happy Indra Wijaya";

        byte[] pdfBytes = reportService.generateReport(name);

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_PDF)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=report.pdf")
                .body(pdfBytes);
    }

}

Semua kode program lengkap dari contoh diatas dapat diakses disini.

ref: