This commit is contained in:
lunaticbum 2025-08-18 18:44:11 +09:00
parent b34750099e
commit f7f71ca195
2 changed files with 69 additions and 30 deletions

View File

@ -12,6 +12,8 @@ import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import java.net.URLConnection
import java.util.regex.Pattern
object CommonUtils {
fun dpToPx(context: Context, dp: Float): Int {
@ -27,48 +29,90 @@ object CommonUtils {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
}
fun getFileTypeBySignature(file: File): String? {
val buffer = ByteArray(12) // 동영상 포맷 확인용으로 충분히 크게 버퍼 확장
file.inputStream().use { it.read(buffer, 0, buffer.size) }
// GIF
if (buffer.sliceArray(0..5).contentEquals("GIF87a".toByteArray()) ||
buffer.sliceArray(0..5).contentEquals("GIF89a".toByteArray())) {
return "gif"
fun getFileTypeBySignature(file: File): String? {
val buffer = ByteArray(12)
val readBytes = file.inputStream().use { it.read(buffer, 0, buffer.size) }
// 1. 시그니처 검사 (기존 방식)
if (readBytes >= 6) {
val gifSignature1 = "GIF87a".toByteArray(Charsets.US_ASCII)
val gifSignature2 = "GIF89a".toByteArray(Charsets.US_ASCII)
if (buffer.copyOfRange(0, 6).contentEquals(gifSignature1)
|| buffer.copyOfRange(0, 6).contentEquals(gifSignature2)
) {
return "gif"
}
}
// JPEG
if (buffer[0] == 0xFF.toByte() && buffer[1] == 0xD8.toByte() && buffer[2] == 0xFF.toByte()) {
if (readBytes >= 3 &&
buffer[0] == 0xFF.toByte() && buffer[1] == 0xD8.toByte() && buffer[2] == 0xFF.toByte()
) {
return "jpg"
}
// PNG
if (buffer.sliceArray(0..7).contentEquals(byteArrayOf(0x89.toByte(),'P'.toByte(),'N'.toByte(),'G'.toByte(),0x0D,0x0A,0x1A,0x0A))) {
if (readBytes >= 8 &&
buffer.copyOfRange(0, 8).contentEquals(
byteArrayOf(
0x89.toByte(), 'P'.toByte(), 'N'.toByte(), 'G'.toByte(),
0x0D, 0x0A, 0x1A, 0x0A
)
)
) {
return "png"
}
// MP4 (ftyp... 브랜드 체크, 보통 4~8바이트 확인)
// "ftyp"는 4바이트 offset 4 ~ 7에 위치
if (buffer.size >= 12 && buffer.sliceArray(4..7).contentEquals("ftyp".toByteArray())) {
if (readBytes >= 12 &&
buffer.copyOfRange(4, 8).contentEquals("ftyp".toByteArray(Charsets.US_ASCII))
) {
return "mp4"
}
// AVI (큰 헤더 "RIFF....AVI ")
if (buffer.size >= 12 &&
buffer.sliceArray(0..3).contentEquals("RIFF".toByteArray()) &&
buffer.sliceArray(8..11).contentEquals("AVI ".toByteArray())) {
if (readBytes >= 12 &&
buffer.copyOfRange(0, 4).contentEquals("RIFF".toByteArray(Charsets.US_ASCII)) &&
buffer.copyOfRange(8, 12).contentEquals("AVI ".toByteArray(Charsets.US_ASCII))
) {
return "avi"
}
// MKV (Matroska) - EBML 헤더: 0x1A 0x45 0xDF 0xA3
if (buffer.size >= 4 &&
buffer[0] == 0x1A.toByte() && buffer[1] == 0x45.toByte() &&
buffer[2] == 0xDF.toByte() && buffer[3] == 0xA3.toByte()) {
if (readBytes >= 4 &&
buffer[0] == 0x1A.toByte() &&
buffer[1] == 0x45.toByte() &&
buffer[2] == 0xDF.toByte() &&
buffer[3] == 0xA3.toByte()
) {
return "mkv"
}
// 2. MIME 타입 검사 (Optional, 정확도 향상)
val mimeType = URLConnection.guessContentTypeFromStream(file.inputStream())
if (mimeType != null) {
when {
mimeType.equals("image/gif", ignoreCase = true) -> return "gif"
mimeType.equals("image/jpeg", ignoreCase = true) -> return "jpg"
mimeType.equals("image/png", ignoreCase = true) -> return "png"
mimeType.startsWith("video/mp4", ignoreCase = true) -> return "mp4"
mimeType.startsWith("video/x-msvideo", ignoreCase = true) -> return "avi"
mimeType.startsWith("video/x-matroska", ignoreCase = true) -> return "mkv"
}
}
// 3. 정규식 기반 시그니처 검사 (GIF 전용 예)
if (readBytes >= 6) {
val sigStr = String(buffer, 0, 6, Charsets.US_ASCII)
val gifPattern = Pattern.compile("GIF8[79]a")
if (gifPattern.matcher(sigStr).matches()) {
return "gif"
}
}
return null
}
fun downloadFileWithOkHttp(context: Context,refferer : Uri, fileUrl: String) {
android.app.AlertDialog.Builder(context)
.setTitle("파일 다운로드")
@ -95,15 +139,12 @@ object CommonUtils {
).show()
}
} else {
// Content-Type에서 확장자 추출
val contentType = response.header("Content-Type")
Blog.LOGE("downloadFileWithOkHttp contentType $contentType")
var extension = contentType?.let {
MimeTypeMap.getSingleton().getExtensionFromMimeType(it)
}
// 확장자 없으면 URL에서 추출하거나 기본값 "dat" 사용
if (extension.isNullOrBlank()) {
extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl)
@ -112,9 +153,6 @@ object CommonUtils {
}
}
Blog.LOGE("downloadFileWithOkHttp extension $extension")
// if (extension.equals("bin")){
//// extension = "jpg"
// }
val fileName =
"${
refferer.host?.replace(
@ -133,6 +171,7 @@ object CommonUtils {
val resultFile = if (extension in listOf("bin", "dat")) {
val realExt = getFileTypeBySignature(file)
Blog.LOGE("downloadFileWithOkHttp extension $realExt")
when {
realExt.isNullOrBlank() -> file
realExt == extension -> file
@ -142,7 +181,7 @@ object CommonUtils {
",",
"_"
)
}_${System.currentTimeMillis()}.$extension")
}_${System.currentTimeMillis()}.$realExt")
if (file.renameTo(newFile)) newFile else file
}
}