///
This commit is contained in:
parent
b34750099e
commit
f7f71ca195
@ -12,6 +12,8 @@ import kotlinx.coroutines.withContext
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.net.URLConnection
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
object CommonUtils {
|
object CommonUtils {
|
||||||
fun dpToPx(context: Context, dp: Float): Int {
|
fun dpToPx(context: Context, dp: Float): Int {
|
||||||
@ -27,48 +29,90 @@ object CommonUtils {
|
|||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
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()) ||
|
fun getFileTypeBySignature(file: File): String? {
|
||||||
buffer.sliceArray(0..5).contentEquals("GIF89a".toByteArray())) {
|
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"
|
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"
|
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"
|
return "png"
|
||||||
}
|
}
|
||||||
|
|
||||||
// MP4 (ftyp... 브랜드 체크, 보통 4~8바이트 확인)
|
if (readBytes >= 12 &&
|
||||||
// "ftyp"는 4바이트 offset 4 ~ 7에 위치
|
buffer.copyOfRange(4, 8).contentEquals("ftyp".toByteArray(Charsets.US_ASCII))
|
||||||
if (buffer.size >= 12 && buffer.sliceArray(4..7).contentEquals("ftyp".toByteArray())) {
|
) {
|
||||||
return "mp4"
|
return "mp4"
|
||||||
}
|
}
|
||||||
|
|
||||||
// AVI (큰 헤더 "RIFF....AVI ")
|
if (readBytes >= 12 &&
|
||||||
if (buffer.size >= 12 &&
|
buffer.copyOfRange(0, 4).contentEquals("RIFF".toByteArray(Charsets.US_ASCII)) &&
|
||||||
buffer.sliceArray(0..3).contentEquals("RIFF".toByteArray()) &&
|
buffer.copyOfRange(8, 12).contentEquals("AVI ".toByteArray(Charsets.US_ASCII))
|
||||||
buffer.sliceArray(8..11).contentEquals("AVI ".toByteArray())) {
|
) {
|
||||||
return "avi"
|
return "avi"
|
||||||
}
|
}
|
||||||
|
|
||||||
// MKV (Matroska) - EBML 헤더: 0x1A 0x45 0xDF 0xA3
|
if (readBytes >= 4 &&
|
||||||
if (buffer.size >= 4 &&
|
buffer[0] == 0x1A.toByte() &&
|
||||||
buffer[0] == 0x1A.toByte() && buffer[1] == 0x45.toByte() &&
|
buffer[1] == 0x45.toByte() &&
|
||||||
buffer[2] == 0xDF.toByte() && buffer[3] == 0xA3.toByte()) {
|
buffer[2] == 0xDF.toByte() &&
|
||||||
|
buffer[3] == 0xA3.toByte()
|
||||||
|
) {
|
||||||
return "mkv"
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun downloadFileWithOkHttp(context: Context,refferer : Uri, fileUrl: String) {
|
fun downloadFileWithOkHttp(context: Context,refferer : Uri, fileUrl: String) {
|
||||||
android.app.AlertDialog.Builder(context)
|
android.app.AlertDialog.Builder(context)
|
||||||
.setTitle("파일 다운로드")
|
.setTitle("파일 다운로드")
|
||||||
@ -95,15 +139,12 @@ object CommonUtils {
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
// Content-Type에서 확장자 추출
|
// Content-Type에서 확장자 추출
|
||||||
val contentType = response.header("Content-Type")
|
val contentType = response.header("Content-Type")
|
||||||
Blog.LOGE("downloadFileWithOkHttp contentType $contentType")
|
Blog.LOGE("downloadFileWithOkHttp contentType $contentType")
|
||||||
var extension = contentType?.let {
|
var extension = contentType?.let {
|
||||||
MimeTypeMap.getSingleton().getExtensionFromMimeType(it)
|
MimeTypeMap.getSingleton().getExtensionFromMimeType(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 확장자 없으면 URL에서 추출하거나 기본값 "dat" 사용
|
// 확장자 없으면 URL에서 추출하거나 기본값 "dat" 사용
|
||||||
if (extension.isNullOrBlank()) {
|
if (extension.isNullOrBlank()) {
|
||||||
extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl)
|
extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl)
|
||||||
@ -112,9 +153,6 @@ object CommonUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Blog.LOGE("downloadFileWithOkHttp extension $extension")
|
Blog.LOGE("downloadFileWithOkHttp extension $extension")
|
||||||
// if (extension.equals("bin")){
|
|
||||||
//// extension = "jpg"
|
|
||||||
// }
|
|
||||||
val fileName =
|
val fileName =
|
||||||
"${
|
"${
|
||||||
refferer.host?.replace(
|
refferer.host?.replace(
|
||||||
@ -133,6 +171,7 @@ object CommonUtils {
|
|||||||
|
|
||||||
val resultFile = if (extension in listOf("bin", "dat")) {
|
val resultFile = if (extension in listOf("bin", "dat")) {
|
||||||
val realExt = getFileTypeBySignature(file)
|
val realExt = getFileTypeBySignature(file)
|
||||||
|
Blog.LOGE("downloadFileWithOkHttp extension $realExt")
|
||||||
when {
|
when {
|
||||||
realExt.isNullOrBlank() -> file
|
realExt.isNullOrBlank() -> file
|
||||||
realExt == extension -> file
|
realExt == extension -> file
|
||||||
@ -142,7 +181,7 @@ object CommonUtils {
|
|||||||
",",
|
",",
|
||||||
"_"
|
"_"
|
||||||
)
|
)
|
||||||
}_${System.currentTimeMillis()}.$extension")
|
}_${System.currentTimeMillis()}.$realExt")
|
||||||
if (file.renameTo(newFile)) newFile else file
|
if (file.renameTo(newFile)) newFile else file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user