Search code examples
androidkotlinhttpurlconnectionokhttpkotlin-coroutines

How to download pdf from url through ok http in kotlin coroutine


I want to download pdf from url using ok HTTP in kotlin. I didn't find the proper solution in coroutine how it be done through. After downloading i want to store in device and show in pdf viewer. When user close the activity the store file automatically delete form internal storage. Does anyone know how to do that. Thanks in advance

class FileDownloader {

    companion object {
        private const val BUFFER_LENGTH_BYTES = 1024 * 8
        private const val HTTP_TIMEOUT = 30
    }

    private var okHttpClient: OkHttpClient

    init {
        val okHttpBuilder = okHttpClient.newBuilder()
            .connectTimeout(HTTP_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .readTimeout(HTTP_TIMEOUT.toLong(), TimeUnit.SECONDS)
        this.okHttpClient = okHttpBuilder.build()
    }

    fun download(url: String, file: File): {
            val request = Request.Builder().url(url).build()
            val response = okHttpClient.newCall(request).execute()
            val body = response.body
            val responseCode = response.code
            if (responseCode >= HttpURLConnection.HTTP_OK &&
                responseCode < HttpURLConnection.HTTP_MULT_CHOICE &&
                body != null) {
                val length = body.contentLength()
                body.byteStream().apply {
                    file.outputStream().use { fileOut ->
                        var bytesCopied = 0
                        val buffer = ByteArray(BUFFER_LENGTH_BYTES)
                        var bytes = read(buffer)
                        while (bytes >= 0) {
                            fileOut.write(buffer, 0, bytes)
                            bytesCopied += bytes
                            bytes = read(buffer)
                        }
                    }
                }
            } else {
                throw IllegalArgumentException("Error occurred when do http get $url")
            }
        }
    }
}

This is not working also how to work with coroutine and remove the file when user close the activity.


Solution

  • You can basically save your file to your download folder.

    what you have to do is; first add read, write permissions to yor manifest file,

    Android defines the following storage-related permissions: READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, and MANAGE_EXTERNAL_STORAGE.

    then you should use content resolver for android version higher than 10. for example

        val content = ContentValues().apply {
                    put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
                    put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
                }
    val uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, content)
    uri?.let {
          contentResolver.openOutputStream(uri)?.apply {
              BufferedOutputStream(this).write(bytes)
              }
          }
    

    but if your android version is lower than 10 you can use this example

     val directory = File(
                        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath
                ).apply {
                    if (!exists()) {
                        mkdir()
                    }
                }
                val file = File(directory, fileName)
                if (!file.exists()) {
                    FileOutputStream(
                            File(directory, fileName)
                    ).write(bytes)
                }
                uri = Uri.fromFile(file)
    

    for more information check this guide https://developer.android.com/training/data-storage