Files
TrisolarisServer/src/main/kotlin/com/android/trisolarisserver/component/EmailStorage.kt
androidlover5842 6b6d84e40a more codes
2026-01-24 22:22:37 +05:30

124 lines
4.5 KiB
Kotlin

package com.android.trisolarisserver.component
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPage
import org.apache.pdfbox.pdmodel.PDPageContentStream
import org.apache.pdfbox.pdmodel.common.PDRectangle
import org.apache.pdfbox.pdmodel.font.PDType1Font
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.time.OffsetDateTime
import java.util.UUID
@Component
class EmailStorage(
@Value("\${storage.emails.root:/home/androidlover5842/docs/emails}")
private val rootPath: String
) {
fun storePdf(propertyId: UUID?, messageId: String?, subject: String?, body: String): String {
val dir = if (propertyId != null) {
Paths.get(rootPath, propertyId.toString())
} else {
Paths.get(rootPath, "unassigned")
}
Files.createDirectories(dir)
val safeName = (messageId ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.pdf"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
val document = PDDocument()
val page = PDPage(PDRectangle.LETTER)
document.addPage(page)
val header = "Subject: ${subject ?: ""}\n\n"
writeText(document, page, header + body)
document.save(tmp.toFile())
document.close()
atomicMove(tmp, path)
return path.toString()
}
private fun writeText(document: PDDocument, firstPage: PDPage, text: String) {
var page = firstPage
var y = 730f
val marginX = 50f
val lineHeight = 14f
val maxLines = 48
var linesOnPage = 0
var content = PDPageContentStream(document, page)
content.beginText()
content.setFont(PDType1Font.HELVETICA, 11f)
content.newLineAtOffset(marginX, y)
fun newLine() {
content.newLineAtOffset(0f, -lineHeight)
y -= lineHeight
linesOnPage++
if (linesOnPage >= maxLines) {
content.endText()
content.close()
page = PDPage(PDRectangle.LETTER)
document.addPage(page)
content = PDPageContentStream(document, page)
content.beginText()
content.setFont(PDType1Font.HELVETICA, 11f)
y = 730f
linesOnPage = 0
content.newLineAtOffset(marginX, y)
}
}
val lines = text.split("\n")
for (line in lines) {
val chunks = line.chunked(90)
for (chunk in chunks) {
content.showText(chunk)
newLine()
}
}
content.endText()
content.close()
}
fun storeEml(propertyId: UUID?, messageId: String?, rawBytes: ByteArray): String {
val dir = if (propertyId != null) {
Paths.get(rootPath, propertyId.toString(), "raw")
} else {
Paths.get(rootPath, "unassigned", "raw")
}
Files.createDirectories(dir)
val safeName = (messageId ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.eml"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
Files.write(tmp, rawBytes)
atomicMove(tmp, path)
return path.toString()
}
fun storeUploadedPdf(propertyId: UUID, originalName: String?, bytes: ByteArray): String {
val dir = Paths.get(rootPath, propertyId.toString(), "manual")
Files.createDirectories(dir)
val safeName = (originalName ?: UUID.randomUUID().toString()).replace(Regex("[^A-Za-z0-9._-]"), "_")
val fileName = "${safeName}_${OffsetDateTime.now().toEpochSecond()}.pdf"
val path = dir.resolve(fileName).normalize()
val tmp = dir.resolve("${fileName}.tmp").normalize()
Files.write(tmp, bytes)
atomicMove(tmp, path)
return path.toString()
}
private fun atomicMove(tmp: Path, target: Path) {
try {
Files.move(tmp, target, java.nio.file.StandardCopyOption.ATOMIC_MOVE, java.nio.file.StandardCopyOption.REPLACE_EXISTING)
} catch (_: Exception) {
Files.move(tmp, target, java.nio.file.StandardCopyOption.REPLACE_EXISTING)
}
}
}