Skip to content

How to download files using storage? #530

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
SirFilbido opened this issue Jun 11, 2024 · 8 comments
Closed

How to download files using storage? #530

SirFilbido opened this issue Jun 11, 2024 · 8 comments

Comments

@SirFilbido
Copy link

I have implemented the storage library but I am having difficulty downloading files.

In my case, I have to download .zip files in the commonMain package.

Does the SDK currently have this type of implementation? If not, would I have to implement it on the native side to then use it in the shared environment?

@BasBuijsen
Copy link
Contributor

Im not a maintainer or anything but i have been working on some storage improvements. There is currently no implementation for this.

You can add the functionality by updating the expected class in commonMain and then you can use the native SDKs to provide the actual implementations.

I don't know what kind of files you want to download but you can also access the download url of a reference. That way you can use your http client to download these files as long as this functionality is not available yet.

@SirFilbido
Copy link
Author

Thanks for the tips @BasBuijsen , I'll try to implement the download via the file's URL. In my case, they are .zip files

But I'm having another problem and I don't know if the SDK supports this. I have some different databases in the storage. I need to configure the address that is not in the google-services.json file.

On Android I can do it like this

val storage = Firebase.storage(BuildConfig.BUCKET_SINC)

How would I do this in Firebase SDK?

@BasBuijsen
Copy link
Contributor

@SirFilbido as far as i can see there is no support for this yet.

@BasBuijsen
Copy link
Contributor

@SirFilbido i had some time to spare so i created the getters for Firebase storage with a custom url.

@SirFilbido
Copy link
Author

Great news, thanks @BasBuijsen.

@yuroyami
Copy link

You can download files using Ktor HTTP client. Here's a minimal snippet that combines GitLive's Firebase Storage and Ktor, to download a file:

val link = Firebase.storage.reference.child(path).getDownloadUrl()

val client = HttpClient(CIO) {
    install(Logging) {
        level = LogLevel.INFO
    }
}

client.prepareGet(url = Url(link)).execute { httpResponse ->
                val channel: ByteReadChannel = httpResponse.body()

                while (!channel.isClosedForRead) {
                    val packet = channel.readRemaining(DEFAULT_HTTP_BUFFER_SIZE.toLong())
                    while (!packet.isEmpty) {
                        val bytes = packet.readBytes()
                        
                        //todo: do something with the received bytes, for example, you can add them to a mutable byte array
                    }
                }
            }

You can extend this example by using kotlinx.io which allows you to write to platform-specific files from common code using sink()

@dogeweb
Copy link

dogeweb commented Aug 23, 2024

Hi,

commonMain:

expect suspend fun getFile(path: String): Result<String> 

androidMain:

private const val ONE_MEGABYTE: Long = 1024 * 1024

actual suspend fun getFile(path: String): Result<String> {
    return try {
        Firebase.storage.android.getReference(path).getBytes(ONE_MEGABYTE).await().let { Result.success(String(it)) }
    } catch (e: Exception) {   
        Result.failure(e)
    }
}

iosMain:

private const val ONE_MEGABYTE: Long = 1024 * 1024

@OptIn(ExperimentalForeignApi::class)
actual suspend fun getFile(path: String): Result<String> {
    return withTimeoutOrNull(1000) {
        suspendCancellableCoroutine { cont ->
            Firebase.storage.ios.referenceWithPath(path).dataWithMaxSize(ONE_MEGABYTE) { data, error ->
                if ((error != null && error != nil) || data == null)
                    cont.resume(Result.failure(Exception("File not found")))
                else
                    cont.resume(Result.success(data.toByteArray().toKString()))
            }
        }
    } ?: Result.failure(Exception("Timeout"))
}

@nbransby
Copy link
Member

I believe the original issue is solved now

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants