File Uploads

LAST EDIT Apr 08 2021

The channel.sendImage and channel.sendFile methods make it easy to upload files.

This functionality defaults to using the Stream CDN. If you would like, you can easily change the logic to upload to your own CDN of choice.
The maximum file size is 20mb for the Stream Chat CDN.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const promises = [ 
    channel.sendImage( 
        fs.createReadStream('./helloworld.jpg'), 
        'hello_world1.jpg', 
    ), 
    channel.sendImage( 
        fs.createReadStream('./helloworld.jpg'), 
        'hello_world2.jpg', 
    ), 
]; 
 
const results = await Promise.all(promises); 
 
const attachments = results.map(response => { 
    return { 
        type: 'image', 
        thumb_url: response.file, 
        asset_url: response.file, 
    }; 
}); 
 
const response = await channel.sendMessage({ 
    text: 'Check out what I have uploaded in parallel', 
    attachments, 
}); 
 
expect(response.message.attachments).to.equal(attachments);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
ChannelClient channelClient = client.channel("messaging", "general"); 
 
// Upload an image without detailed progress 
channelClient.sendImage(imageFile).enqueue(result -> { 
    if (result.isSuccess()) { 
        // Successful upload, you can now attach this image 
        // to an message that you then send to a channel 
        String imageUrl = result.data(); 
 
        Attachment attachment = new Attachment(); 
        attachment.setType("image"); 
        attachment.setImageUrl(imageUrl); 
 
        Message message = new Message(); 
        message.getAttachments().add(attachment); 
 
        channelClient.sendMessage(message).enqueue(res -> { /* ... */ }); 
    } 
}); 
 
// Upload a file, monitoring for progress with a ProgressCallback 
channelClient.sendFile(anyOtherFile, new ProgressCallback() { 
    @Override 
    public void onSuccess(@NotNull String file) { 
        String fileUrl = file; 
    } 
 
    @Override 
    public void onError(@NotNull ChatError error) { 
        // Handle error 
    } 
 
    @Override 
    public void onProgress(long progress) { 
        // You can render the uploading progress here 
    } 
}).enqueue(); // No callback passed to enqueue, as we'll get notified above anyway
1
2
3
4
5
6
7
8
9
10
11
12
13
import StreamChat 
 
/// 1: Create a `ChannelId` that represents the channel you want to send a message to. 
let channelId = ChannelId(type: .messaging, id: "general") 
 
/// 2: Use the `ChatClient` to create a `ChatChannelController` with the `ChannelId`. 
let channelController = chatClient.channelController(for: channelId) 
 
/// 3: Call `ChatChannelController.createNewMessage` to create the message. 
channelController.createNewMessage( 
    text: "Hello", 
    attachments: [ChatMessageAttachmentSeed(localURL: URL(string: "./my_image.png")!, fileName: "my_image.png", type: .image)] 
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
val channelClient = client.channel("messaging", "general") 
 
// Upload an image without detailed progress 
channelClient.sendImage(imageFile).enqueue { result-> 
    if (result.isSuccess) { 
        // Successful upload, you can now attach this image 
        // to an message that you then send to a channel 
        val imageUrl = result.data() 
        val attachment = Attachment( 
            type = "image", 
            imageUrl = imageUrl, 
        ) 
        val message = Message( 
            attachments = mutableListOf(attachment), 
        ) 
        channelClient.sendMessage(message).enqueue { /* ... */ } 
    } 
} 
 
// Upload a file, monitoring for progress with a ProgressCallback 
channelClient.sendFile(anyOtherFile, object : ProgressCallback { 
    override fun onSuccess(file: String) { 
        val fileUrl = file 
    } 
 
    override fun onError(error: ChatError) { 
        // Handle error 
    } 
 
    override fun onProgress(progress: Long) { 
        // You can render the uploading progress here 
    } 
}).enqueue() // No callback passed to enqueue, as we'll get notified above anyway
1
2
3
$user = [ 'id' => 'jenny' ]; 
 
$response = $channel->sendImage('http://bit.ly/2O35mws', 'image.jpeg', $user);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
final client = StreamChatClient('api-key'); 
var attachment = Attachment(); 
 
// Upload an image without monitoring send progress 
client.sendImage(image, channelId, channelType).then((response) { 
  // Successful upload, you can now attach this image 
  // to an message that you then send to a channel 
  final imageUrl = response.file; 
  attachment = attachment.copyWith( 
    type: 'image', 
    imageUrl: imageUrl, 
  ); 
  final message = Message(attachments: [attachment]); 
  client.sendMessage(message, channelId, channelType); 
}).catchError((error, stk) { 
  // Handle error 
}); 
 
// Upload an file, monitoring the progress with a onSendProgress callback 
await client.sendFile( 
  file, 
  channelId, 
  channelType, 
  onSendProgress: (sent, total) { 
    // Handle the send progress 
    attachment = attachment.copyWith( 
      uploadState: UploadState.inProgress( 
       uploaded: sent, 
       total: total, 
       ), 
    ); 
  }, 
 ).then((response) { 
   // Successful upload, you can now attach this file 
   // to an message that you then send to a channel 
   final fileUrl = response.file; 
   attachment = attachment.copyWith( 
     type: 'file', 
     assetUrl: fileUrl, 
     uploadState: UploadState.success(), 
   ); 
   final message = Message(attachments: [attachment]); 
   client.sendMessage(message, channelId, channelType); 
 }).catchError((error, stk) { 
   // Handle error 
   attachment = attachment.copyWith( 
     uploadState: UploadState.failed(error: error), 
   ); 
 }); 
 
// Alternatively you can call the sendMessage directly on the channel 
// which will automatically handle all the upload process of the provided 
// attachments. 
final channel = client.channel(channelType, id: channelId); 
 
// Creating a message object with multiple local attachments 
final message = Message(text: 'Hello', attachments: [ 
  Attachment( 
    type: 'image', 
    file: AttachmentFile(path: 'imagePath/imageName.png'), 
  ), 
  Attachment( 
    type: 'file', 
    file: AttachmentFile(path: 'filePath/fileName.pdf'), 
  ), 
]); 
 
// Sending the message to the channel 
await channel.sendMessage(message);

In the code example above, note how the message attachments are created after the files are uploaded. The React components support regular uploads, clipboard pasting, drag and drop, as well as URL enrichment via built-in open-graph scraping. As a bonus, the Stream CDN will automatically handle image resizing for you.

Using Your Own CDN

Copied!

All 5 SDKs make it easy to use your own CDN for uploads. The code examples below show how to change where files are uploaded:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// react sdk 
<MessageInput 
    doFileUploadRequest={(file, channel) => { 
        return client.sendFile('https://customcdn.url', file); // or your custom upload request. 
    }} 
    doImageUploadRequest={(file, channel) => { 
        return client.sendFile('https://customcdn.url', file); // or your custom upload request. 
    }} 
/> 
 
// react-native sdk 
<Channel 
    doDocUploadRequest={(file, channel) => { 
        return client.sendFile('https://customcdn.url', file); // or your custom upload request. 
    }} 
    doImageUploadRequest={(file, channel) => { 
        return client.sendFile('https://customcdn.url', file); // or your custom upload request. 
    }} 
/>
1
2
3
4
// Set a custom FileUploader implementation when building your client 
ChatClient client = new ChatClient.Builder("YOUR_API_KEY", context) 
        .fileUploader(new MyFileUploader()) 
        .build();
1
2
3
4
5
// Set a custom FileUploader implementation when building your client 
val client = ChatClient.Builder("YOUR_API_KEY", context) 
    .fileUploader(MyFileUploader()) 
    .build() 
}
1
2
3
4
5
// Set a custom FileUploader implementation when building your client 
final client = StreamChatClient( 
  'api-key', 
  attachmentFileUploader: MyFileUploader(), 
);
1