Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package co.nilin.opex.storage.app.controller

import co.nilin.opex.storage.app.service.StorageService
import co.nilin.opex.storage.app.service.StringToHashService
import co.nilin.opex.utility.error.data.OpexError
import co.nilin.opex.utility.error.data.OpexException
import kotlinx.coroutines.reactive.awaitFirstOrNull
Expand All @@ -13,55 +14,63 @@ import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Mono
import java.net.URLConnection
import java.nio.file.Paths
import kotlin.io.path.exists
import java.util.*

@RestController
class FileController(private val storageService: StorageService) {
class FileController(private val storageService: StorageService, private val stringToHashService: StringToHashService) {
data class FileUploadResponse(val path: String)

@PostMapping("/{uid}")
suspend fun fileUpload(
@PathVariable("uid") uid: String,
@RequestPart("file") file: Mono<FilePart>,
@CurrentSecurityContext securityContext: SecurityContext
): Any {
if (securityContext.authentication.name != uid) throw OpexException(OpexError.UnAuthorized)
file.awaitFirstOrNull().apply {
if (this == null) throw OpexException(OpexError.BadRequest, "File Not Provided")
val ext = this.filename().replace(Regex(".+(?=\\..+)"), "")
if (ext.toLowerCase() !in listOf(".jpg", ".jpeg", ".png", ".mp4", ".mov", ".pdf", ".svg"))
throw OpexException(OpexError.BadRequest, "Invalid File Format")
val path = Paths.get("").resolve("/opex-storage/$uid/${this.filename()}").toString()
storageService.store(path, this)
return FileUploadResponse("/$uid/${this.filename()}")
private suspend fun upload(uid: String, file: FilePart?, nameWithoutExtension: String? = null): FileUploadResponse {
if (file == null) throw OpexException(OpexError.BadRequest, "File Not Provided")
val filename = file.filename()
val ext = filename.replace(Regex(".+(?<=\\.)"), "")
if (ext.toLowerCase() !in listOf("jpg", "jpeg", "png", "mp4", "mov", "pdf", "gif"))
throw OpexException(OpexError.BadRequest, "Invalid File Format")
val uri = if (nameWithoutExtension == null) {
"$uid/$filename"
} else {
"$uid/$nameWithoutExtension.$ext"
}
val path = Paths.get("").resolve("/opex-storage/$uri").toString()
storageService.store(path, file)
return FileUploadResponse("/$uri")
}

@GetMapping("/{uid}/{filename}")
@ResponseBody
suspend fun fileDownload(
@PathVariable("uid") uid: String,
@PathVariable("filename") filename: String,
@CurrentSecurityContext securityContext: SecurityContext
): ResponseEntity<ByteArray> {
if (securityContext.authentication.name != uid) throw OpexException(OpexError.UnAuthorized)
private suspend fun download(uid: String, filename: String? = null): ResponseEntity<ByteArray> {
val path = Paths.get("").resolve("/opex-storage/$uid/$filename")
if (!storageService.exists(path.toString())) throw OpexException(OpexError.NotFound)
val file = storageService.load(path.toString())
val mimeType = URLConnection.getFileNameMap().getContentTypeFor(path.fileName.toString())
return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(file.readBytes())
}

@PostMapping("/{uid}")
suspend fun fileUploadPost(
@PathVariable("uid") uid: String,
@RequestPart("file") file: Mono<FilePart>,
@CurrentSecurityContext securityContext: SecurityContext
): FileUploadResponse {
if (securityContext.authentication.name != uid) throw OpexException(OpexError.UnAuthorized)
return upload(uid, file.awaitFirstOrNull(), stringToHashService.digest(UUID.randomUUID().toString()))
}

@GetMapping("/{uid}/{filename}")
@ResponseBody
suspend fun download(
@PathVariable("uid") uid: String,
@PathVariable("filename") filename: String,
@CurrentSecurityContext securityContext: SecurityContext
): ResponseEntity<ByteArray> {
if (securityContext.authentication.name != uid) throw OpexException(OpexError.UnAuthorized)
return download(uid, filename)
}

@GetMapping("/admin/download/{uid}/{filename}")
@ResponseBody
suspend fun adminFileDownload(
@PathVariable("uid") uid: String,
@PathVariable("filename") filename: String
@PathVariable("uid") uid: String,
@PathVariable("filename") filename: String
): ResponseEntity<ByteArray> {
val path = Paths.get("").resolve("/opex-storage/$uid/$filename")
if (!storageService.exists(path.toString())) throw OpexException(OpexError.NotFound)
val file = storageService.load(path.toString())
val mimeType = URLConnection.getFileNameMap().getContentTypeFor(path.fileName.toString())
return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(file.readBytes())
return download(uid, filename)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package co.nilin.opex.storage.app.service

import org.springframework.stereotype.Service
import java.util.zip.CRC32

@Service
class StringToHashService {
private val crc32 = CRC32()

fun digest(input: String): String {
crc32.update(input.toByteArray())
return String.format("%02x", crc32.value)
}
}