diff --git a/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseIn.kt b/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseIn.kt
new file mode 100644
index 000000000..031774376
--- /dev/null
+++ b/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseIn.kt
@@ -0,0 +1,7 @@
+package com.few.api.domain.admin.document.dto
+
+import org.springframework.web.multipart.MultipartFile
+
+data class ConvertContentUseCaseIn(
+ val content: MultipartFile
+)
\ No newline at end of file
diff --git a/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseOut.kt b/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseOut.kt
new file mode 100644
index 000000000..8dfe5a03f
--- /dev/null
+++ b/api/src/main/kotlin/com/few/api/domain/admin/document/dto/ConvertContentUseCaseOut.kt
@@ -0,0 +1,8 @@
+package com.few.api.domain.admin.document.dto
+
+import java.net.URL
+
+data class ConvertContentUseCaseOut(
+ val content: String,
+ val originDownLoadUrl: URL
+)
\ No newline at end of file
diff --git a/api/src/main/kotlin/com/few/api/domain/admin/document/usecase/ConvertContentUseCase.kt b/api/src/main/kotlin/com/few/api/domain/admin/document/usecase/ConvertContentUseCase.kt
new file mode 100644
index 000000000..719036b51
--- /dev/null
+++ b/api/src/main/kotlin/com/few/api/domain/admin/document/usecase/ConvertContentUseCase.kt
@@ -0,0 +1,69 @@
+package com.few.api.domain.admin.document.usecase
+
+import com.few.api.domain.admin.document.dto.ConvertContentUseCaseIn
+import com.few.api.domain.admin.document.dto.ConvertContentUseCaseOut
+import com.few.api.domain.admin.document.service.GetUrlService
+import com.few.api.domain.admin.document.service.dto.GetUrlQuery
+
+import com.few.api.repo.dao.document.DocumentDao
+import com.few.api.repo.dao.document.command.InsertDocumentIfoCommand
+import com.few.storage.document.service.ConvertDocumentService
+import com.few.storage.document.service.PutDocumentService
+import org.springframework.stereotype.Component
+import org.springframework.transaction.annotation.Transactional
+import java.io.File
+import java.time.LocalDate
+import kotlin.random.Random
+
+@Component
+class ConvertContentUseCase(
+ private val documentDao: DocumentDao,
+ private val convertDocumentService: ConvertDocumentService,
+ private val putDocumentService: PutDocumentService,
+ private val getUrlService: GetUrlService
+) {
+ @Transactional
+ fun execute(useCaseIn: ConvertContentUseCaseIn): ConvertContentUseCaseOut {
+ val dateDir = LocalDate.now().toString()
+ val contentSource = useCaseIn.content
+
+ val documentSuffix = contentSource.originalFilename?.substringAfterLast(".") ?: "md"
+ val document = runCatching {
+ File.createTempFile("temp", ".$documentSuffix")
+ }.onSuccess {
+ contentSource.transferTo(it)
+ }.getOrThrow()
+ val documentName = "documents/$dateDir/${generateRandomName()}" + ".$documentSuffix"
+
+ val originDownloadUrl = putDocumentService.execute(documentName, document)?.let { res ->
+ val source = res.`object`
+ GetUrlQuery(source).let { query ->
+ getUrlService.execute(query)
+ }.let { url ->
+ InsertDocumentIfoCommand(
+ path = documentName,
+ url = url
+ ).let { command ->
+ documentDao.insertDocumentIfo(command)
+ }
+ url
+ }
+ } ?: throw IllegalStateException("Failed to put document")
+
+ val html =
+ convertDocumentService.mdToHtml(document.readBytes().toString(Charsets.UTF_8))
+
+ return ConvertContentUseCaseOut(html.replace("\n", "
"), originDownloadUrl)
+ }
+
+ private fun generateRandomName(): String {
+ return randomString()
+ }
+
+ private fun randomString(): String {
+ val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9')
+ return (1..16)
+ .map { Random.nextInt(0, charPool.size).let { charPool[it] } }
+ .joinToString("")
+ }
+}
\ No newline at end of file