|
|
@@ -1,15 +1,31 @@
|
|
|
package co.id.datacomsolusindo.engineservice.report
|
|
|
|
|
|
+import net.sf.jasperreports.engine.*
|
|
|
+import net.sf.jasperreports.engine.export.FileHtmlResourceHandler
|
|
|
+import net.sf.jasperreports.engine.export.HtmlExporter
|
|
|
+import net.sf.jasperreports.engine.export.JRCsvExporter
|
|
|
+import net.sf.jasperreports.engine.export.JRPdfExporter
|
|
|
+import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter
|
|
|
+import net.sf.jasperreports.engine.fill.JRSwapFileVirtualizer
|
|
|
+import net.sf.jasperreports.engine.util.FileBufferedOutputStream
|
|
|
+import net.sf.jasperreports.engine.util.JRSwapFile
|
|
|
+import net.sf.jasperreports.export.*
|
|
|
import org.springframework.beans.factory.annotation.Autowired
|
|
|
import org.springframework.beans.factory.annotation.Value
|
|
|
-import org.springframework.core.annotation.Order
|
|
|
-import org.springframework.stereotype.Service
|
|
|
import java.io.File
|
|
|
+import java.io.IOException
|
|
|
+import java.io.InputStream
|
|
|
+import java.io.OutputStream
|
|
|
import java.nio.file.Files
|
|
|
+import java.nio.file.Path
|
|
|
import java.nio.file.Paths
|
|
|
import java.nio.file.StandardCopyOption
|
|
|
+import java.sql.DriverManager
|
|
|
+import java.util.UUID
|
|
|
+import java.util.zip.ZipEntry
|
|
|
+import java.util.zip.ZipOutputStream
|
|
|
|
|
|
-class ReportService(rptService: RptService) {
|
|
|
+class ReportService(val rptService: RptService) {
|
|
|
|
|
|
@Value("\${spring.datasource.url}")
|
|
|
lateinit var jdbcUrl: String
|
|
|
@@ -26,8 +42,6 @@ class ReportService(rptService: RptService) {
|
|
|
private val projectDir = System.getProperty("user.dir")
|
|
|
private val pathResult = "$projectDir/${rptService.pathResult}"
|
|
|
private val pathPreview = "$projectDir/${rptService.pathPreview}"
|
|
|
-// private val pathResult = "$projectDir/result"
|
|
|
-// private val pathPreview = "$projectDir/preview"
|
|
|
|
|
|
private val logger = ReportLogger.getLogger(this::class.java)
|
|
|
|
|
|
@@ -62,7 +76,7 @@ class ReportService(rptService: RptService) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- private fun generateReport(params: MutableMap<String, Any>, isPreview: Boolean = false): ByteArray? {
|
|
|
+ private fun generateReport(params: MutableMap<String, Any>, isPreview: Boolean = false): InputStream? {
|
|
|
val userSubmitted = params["userSubmitted"].toString()
|
|
|
val reportJob = ReportJob(userSubmitted = userSubmitted, criteria = U.mapper.writeValueAsString(params))
|
|
|
val exist = reportJobRepository.findByJobKeyAndUserSubmitted(reportJob.jobKey, reportJob.userSubmitted)
|
|
|
@@ -81,14 +95,110 @@ class ReportService(rptService: RptService) {
|
|
|
} else null
|
|
|
} else null
|
|
|
|
|
|
- return existReport?.readBytes()?.let {
|
|
|
+ return existReport?.inputStream()?.let {
|
|
|
// update reportJob
|
|
|
+ val rpt = exist.get()
|
|
|
it
|
|
|
} ?: run {
|
|
|
- null
|
|
|
+ val templateFile = "${rptService.pathTemplate}/${params["templateName"]}"
|
|
|
+ val jasperReport = JasperCompileManager.compileReport(templateFile.byteInputStream())
|
|
|
+ generateReportFile(jasperReport, formatType, params)
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private fun generateReportFile(
|
|
|
+ jasperReport: JasperReport,
|
|
|
+ formatType: FormatType,
|
|
|
+ paramReport: MutableMap<String, Any>
|
|
|
+ ): InputStream? {
|
|
|
+ val os = FileBufferedOutputStream()
|
|
|
+
|
|
|
+ DriverManager.getConnection(jdbcUrl, dbUser, dbPass).use { connection ->
|
|
|
+ try {
|
|
|
+ val jasperPrint = JasperFillManager.fillReport(jasperReport, paramReport, connection)
|
|
|
+ val unique = UUID.randomUUID().toString()
|
|
|
+ val tmpDir = "report/swap"
|
|
|
+ File(tmpDir).mkdirs()
|
|
|
+ val vrt = JRSwapFile(tmpDir, 1024, 1024)
|
|
|
+ val reportVirT: JRVirtualizer = JRSwapFileVirtualizer(10, vrt, true)
|
|
|
+ paramReport[JRParameter.REPORT_VIRTUALIZER] = reportVirT
|
|
|
+
|
|
|
+ val exporter = when (formatType) {
|
|
|
+ FormatType.PDF, FormatType.SCREEN -> {
|
|
|
+ val exporter = JRPdfExporter()
|
|
|
+ exporter.exporterOutput = SimpleOutputStreamExporterOutput(os)
|
|
|
+ exporter
|
|
|
+ }
|
|
|
+ FormatType.CSV -> {
|
|
|
+ val cs = SimpleCsvExporterConfiguration()
|
|
|
+ cs.forceFieldEnclosure = true
|
|
|
+ cs.isWriteBOM = true // For UTF-8 BOM
|
|
|
+ cs.fieldDelimiter = "," // Bisa juga pakai ; kalau regional
|
|
|
+ val csvExporter = JRCsvExporter()
|
|
|
+ csvExporter.setConfiguration(cs)
|
|
|
+ csvExporter.exporterOutput = SimpleWriterExporterOutput(os)
|
|
|
+ csvExporter
|
|
|
+ }
|
|
|
+ FormatType.XLSX -> {
|
|
|
+ val exporter = JRXlsxExporter()
|
|
|
+ exporter.exporterOutput = SimpleOutputStreamExporterOutput(os)
|
|
|
+ exporter
|
|
|
+ }
|
|
|
+ FormatType.HTML -> {
|
|
|
+ if (!File(".tmp/$unique").exists()) {
|
|
|
+ File(".tmp/$unique").mkdirs()
|
|
|
+ }
|
|
|
+ //reportGenerateId
|
|
|
+ val file = File(".tmp/$unique/${paramReport["templateName"]}.html")
|
|
|
+ val htmlExp = HtmlExporter()
|
|
|
+ val configuration = SimpleHtmlExporterConfiguration()
|
|
|
+ htmlExp.setConfiguration(configuration)
|
|
|
+
|
|
|
+ val exporterOutput = SimpleHtmlExporterOutput(file)
|
|
|
+ val resourcesDir = File(file.parent, file.name.toString() + "_images")
|
|
|
+ val pathPattern = resourcesDir.name + "/{0}"
|
|
|
+ exporterOutput.imageHandler = FileHtmlResourceHandler(resourcesDir, pathPattern)
|
|
|
+ htmlExp.exporterOutput = exporterOutput
|
|
|
+ htmlExp
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ exporter.setExporterInput(SimpleExporterInput(jasperPrint))
|
|
|
+ exporter.exportReport()
|
|
|
+ if (formatType == FormatType.HTML) {
|
|
|
+ pack(".tmp/$unique", os)
|
|
|
+ }
|
|
|
+ return os.dataInputStream
|
|
|
+ } catch (e: Exception) {
|
|
|
+ logger.error("failed to generate report", e);
|
|
|
+ throw (e)
|
|
|
+ } finally {
|
|
|
+ os.flush()
|
|
|
+ os.close()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun pack(sourceDirPath: String, os: OutputStream): OutputStream {
|
|
|
+ ZipOutputStream(os).use { zs ->
|
|
|
+ val pp: Path = Paths.get(sourceDirPath)
|
|
|
+ Files.walk(pp)
|
|
|
+ .filter { path -> !Files.isDirectory(path) }
|
|
|
+ .forEach { path ->
|
|
|
+ val zipEntry = ZipEntry(pp.relativize(path).toString())
|
|
|
+ try {
|
|
|
+ zs.putNextEntry(zipEntry)
|
|
|
+ Files.copy(path, zs)
|
|
|
+ zs.closeEntry()
|
|
|
+ } catch (e: IOException) {
|
|
|
+ logger.error("failed zip pack", e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return os
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|