Seize the day

POST : Android Dev Study

간단한 UrlDownloader 구현

URL 이미지 혹은 파일을 특정 디렉토리에 다운로드하는 간단한 클래스를 만들었다.  간단하지만 예외 케이스에 최대한 대응하도록 견고하게 구현했다. 

OkHttp3

implementation("com.squareup.okhttp3:okhttp:4.9.0")

 

AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />

 

UrlDownloader

import androidx.annotation.WorkerThread
import java.io.File
import java.io.IOException
import okhttp3.OkHttpClient
import okhttp3.Request
import okio.sink

class UrlDownloader(
    private val url: String,
    private val headers: Map<String, String>?,
    private val file: File,
) {
    @WorkerThread
    @Throws(Exception::class)
    fun download(): File {
        val destDirectory: File = checkNotNull(file.parentFile)
        if (!destDirectory.exists()) {
            destDirectory.mkdirs()
        }
        val tempFile = File.createTempFile("temp_", null, destDirectory)
        
        try {
            downloadToTempFile(tempFile)
            if (!tempFile.renameTo(file)) {
                throw IOException("Failed rename to target file")
            }
            return file
        } catch (ex: Exception) {
            tempFile.delete()
            throw ex
        }
    }

    private fun downloadToTempFile(tempFile: File) {
        val request = Request.Builder()
            .url(url)
            .addHeaders()
            .build()
        
        okHttpClient.newCall(request).execute().use { response ->
            if (!response.isSuccessful) {
                throw IOException("invalid response code: ${response.code}")
            }
            tempFile.sink().use {
                checkNotNull(response.body).source().readAll(it)
            }
        }
    }

    private fun Request.Builder.addHeaders() = apply {
        headers?.entries?.forEach {
            addHeader(it.key, it.value)
        }
    }
    
    companion object {
        private val okHttpClient = OkHttpClient()
    }
}

 

Test code

private fun test() {
    val url =
        "https://1.bp.blogspot.com/-73nbn4r0Imk/YKMtQF8ZPlI/AAAAAAAAQjs/TzvtHpXiFNcQJUM-ltLvyFRv7ezLwpWugCLcBGAsYHQ/s0/Untitled.jpeg"
    val file = File(externalCacheDir, "dir4/2.jpg")

    Thread {
        UrlDownloader(url, headers = null, file).download()
    }.start()
}
top

posted at

2022. 1. 28. 16:32


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크