File Uploads

Stream Chat provides methods to upload files like images, videos and more to the Stream CDN or to your own CDN. This allows you to use them, for example, as attachments in messages, user avatars or channel avatars.

Uploading files

When uploading a file, it can belong to a channel so that it can be used as an attachment in a message, or it can be a standalone file to be used anywhere in your application, like a user profile image or channel avatar.

Attachments

For uploading files as message attachments in a channel, you can either send the attachment directly as part of the message and let the SDK handle the upload progress, or you can upload the file to the channel first, and then attach it to the message.

var jpegFile = File.ReadAllBytes("helloworld.jpg");

await messageClient.UploadImageAsync(channel.Type, channel.Id, user, jpegFile, "helloworld.jpg");

Standalone

In some cases, you may need to upload files that are not tied to a specific channel or message. For example, uploading a user profile image or channel avatar. These uploads are independent and can be used anywhere in your application.

import StreamChat

// Upload an image to the CDN.
let chatClient = ChatClient.shared
let imageLocalFileUrl = try image.tempLocalFileUrl()
chatClient.uploadAttachment(
    localUrl: imageLocalFileUrl,
    progress: { progressValue in
        // Track upload progress (0.0 to 1.0)
    },
    completion: { result in
        switch result {
        case .success(let uploadedFile):
            let remoteUrl = uploadedFile.url
            // Example: Update user avatar
            chatClient.currentUserController().updateUserData(
                imageURL: remoteUrl
            )
        case .failure(let error):
            // Handle upload error
        }
    }
)

/// Example on how to save an image to a temporary file URL.
extension UIImage {
    func tempLocalFileUrl() throws -> URL? {
        guard let imageData = jpegData(compressionQuality: 1.0) else { return nil }
        let imageName = "\(UUID().uuidString).jpg"
        let localPath = NSTemporaryDirectory().appending(imageName)
        let photoURL = URL(fileURLWithPath: localPath)
        try imageData.write(to: photoURL)
        return photoURL
    }
}

Deleting files

If you want to save storage space you can delete the uploaded files.

// Delete File
await messageClient.DeleteFileAsync("<channel-type>", "<channel-id>", url);

// Delete Image
await messageClient.DeleteImageAsync("<channel-type>", "<channel-id>", url);

File Requirements

Stream has specific requirements for the files that can be uploaded to the CDN.

Images

  • Stream supported image types are: image/bmp, image/gif, image/jpeg, image/png, image/webp, image/heic, image/heic-sequence, image/heif, image/heif-sequence, image/svg+xml.

  • You can set a more restrictive list for your application if needed.

  • The maximum file size is 100MB.

Other Files

  • Stream will not block any file types from uploading, however, different clients may handle different types differently or not at all.

  • You can set a more restrictive list for your application if needed.

  • The maximum file size is 100MB.

Allow / Block file extensions

Stream will allow any file extension. If you want to be more restrictive for an application, this is can be set via API or by logging into your dashboard.

  • To update via the dashboard, login and go to the Chat Overview page >> Upload Configuration

  • API updates are made using UpdateAppSettings, see the App Settings page

The Stream CDN URL returned during the upload contains a signature that validates the access to the file it points to. Only the members of a channel a file was uploaded to can see the attachment and its unique, signed link. Links can only be accessed with a valid signature, which also protects against enumeration attacks.

Whenever messages containing your attachments are retrieved (i.e., when querying a channel), the attachment links will contain a new, fresh signature.

A single Stream CDN URL expires after 14 days, after which its signature will stop working and the link won’t be valid anymore. You can check when a link will expire by comparing the current time with the Unix timestamp in the Expires parameter of the link’s query: https://us-east.stream-io-cdn.com/0000/images/foo.png?…&Expires=1602666347&…

As explained above, all operations that return messages will refresh links automatically, but if you are storing a message containing an expired link you can perform a getMessage call to retrieve fresh links for its attachments.

Image resizing

You can automatically resize an image appending query parameters to a valid image link stored on the Stream CDN.

An image can only be resized if the total pixel count of the source image is 16.800.000 or less. Attempting to resize an image with more pixels will result in an API error. An image of 4000 by 4000 would be accepted, but an image of 4100 by 4100 would pass the upper treshold for resizing.

There are four supported params - all of them are optional and can be used interchangeably:

ParameterTypeValuesDescription
wnumberWidth
hnumberHeight
resizestringclip, crop, scale, fillThe resizing mode
cropstringcenter, top, bottom, left, rightThe cropping direction during resize

Resized images will count against your stored files quota.

Using your own CDN

All SDKs make it easy to use your own CDN for file uploads. The code examples below show how to use a custom CDN client.

// Set a custom FileUploader implementation when building your client
val client = ChatClient.Builder("{{ api_key }}", context)
  .fileUploader(MyFileUploader())
  .build()
}
© Getstream.io, Inc. All Rights Reserved.