Attachment Downloads

The Stream Chat SDK supports uploading photos, audio, voice recordings, videos, and other file types. Uploaded files are represented as message attachments. The SDK also provides a convenient way to download these attachments to the device's public Downloads directory using Android's DownloadManager.

Downloading Attachments

Use the ChatClient.downloadAttachment() extension function to download an attachment:

public fun ChatClient.downloadAttachment(
    context: Context,
    attachment: Attachment,
    generateDownloadUri: (Attachment) -> Uri,
    interceptRequest: DownloadManager.Request.() -> Unit = {},
): Call<Unit>

Parameters

ParameterDescription
contextThe Android context.
attachmentThe Attachment object to download.
generateDownloadUriA lambda that generates the download Uri from the attachment. Typically returns attachment.assetUrl or attachment.imageUrl parsed as a URI.
interceptRequestOptional lambda to customize the DownloadManager.Request before enqueueing (e.g., add headers, change notification visibility).

Basic Usage

val attachment: Attachment = message.attachments.first()

ChatClient.instance().downloadAttachment(
    context = context,
    attachment = attachment,
    generateDownloadUri = { it.assetUrl?.toUri() ?: it.imageUrl?.toUri()!! },
    interceptRequest = { /* add custom headers, change notification visibility... */ },
).enqueue { result ->
    when (result) {
        is Result.Success -> {
            // Download started successfully
        }
        is Result.Failure -> {
            // Handle error
        }
    }
}

Default Behavior

The download:

  • Saves to the public Downloads directory (Environment.DIRECTORY_DOWNLOADS)
  • Uses the attachment's name, title, or a fallback name derived from the URL
  • Shows a notification when the download completes (VISIBILITY_VISIBLE_NOTIFY_COMPLETED)

This method uses Android's system DownloadManager, which handles the download in the background and survives app restarts. The downloaded file is saved to the device's public Downloads folder and is accessible to the user via a file manager.

Customizing Downloads in UI SDKs

Both the XML and Compose UI SDKs use ChatClient.downloadAttachment() internally when users tap the download button on attachments. You can customize this behavior by providing your own implementations of:

  • DownloadAttachmentUriGenerator: Controls how the download URI is generated from an attachment.
  • DownloadRequestInterceptor: Allows modifying the DownloadManager.Request before it is enqueued.

DownloadAttachmentUriGenerator

public fun interface DownloadAttachmentUriGenerator {
    public fun generateDownloadUri(attachment: Attachment): Uri
}

The default implementation (DefaultDownloadAttachmentUriGenerator) returns the attachment's assetUrl or imageUrl:

public object DefaultDownloadAttachmentUriGenerator : DownloadAttachmentUriGenerator {
    override fun generateDownloadUri(attachment: Attachment): Uri =
        Uri.parse(attachment.assetUrl ?: attachment.imageUrl)
}

DownloadRequestInterceptor

public fun interface DownloadRequestInterceptor {
    public fun intercept(request: DownloadManager.Request)
}

Use this to add headers, change notification visibility, or apply other customizations to the download request.

Configuration

XML UI Components

Set the customizations on ChatUI:

// Custom URI generator (e.g., for signed URLs)
ChatUI.downloadAttachmentUriGenerator = DownloadAttachmentUriGenerator { attachment ->
    val signedUrl = signingService.sign(attachment.assetUrl ?: attachment.imageUrl)
    Uri.parse(signedUrl)
}

// Custom request interceptor (e.g., for authentication headers)
ChatUI.downloadRequestInterceptor = DownloadRequestInterceptor { request ->
    request.addRequestHeader("Authorization", "Bearer ${authRepository.getToken()}")
}

Compose UI Components

Pass the customizations to ChatTheme:

ChatTheme(
    downloadAttachmentUriGenerator = DownloadAttachmentUriGenerator { attachment ->
        val signedUrl = signingService.sign(attachment.assetUrl ?: attachment.imageUrl)
        Uri.parse(signedUrl)
    },
    downloadRequestInterceptor = DownloadRequestInterceptor { request ->
        request.addRequestHeader("Authorization", "Bearer ${authRepository.getToken()}")
    },
) {
    // Your chat UI content
}

Clearing Cache and Temporary Files

The SDK caches attachments and other files locally to improve performance. To clear all cached and temporary files (e.g., to free up disk space or when the user logs out), use the ChatClient.clearCacheAndTemporaryFiles() method:

ChatClient.instance().clearCacheAndTemporaryFiles(context).enqueue { result ->
    when (result) {
        is Result.Success -> {
            // Cache cleared successfully
        }
        is Result.Failure -> {
            // Handle error
        }
    }
}

This method clears both the internal cache directories and any temporary files stored in external storage.

This operation does NOT delete files downloaded to the public Downloads directory using the ChatClient.downloadAttachment(). Those files are no longer managed by the SDK and must be deleted manually by the user if desired.

This operation is available starting from version 6.32.0 of the Android SDK.