Send and Receive Images

Overview

This guide covers sending and receiving images within a conversation.

Before you begin, make sure you added the SDK to your app and you are able to create a conversation.

NOTE: A step-by-step tutorial to build a chat application is available here.

This guide will make use of the following concepts:

  • Conversation Events - message events that fire on a Conversation, after you are a Member

Send an Image

Given a conversation you are already a member of:

// Scenario #1: Send an image from a URL
conversation.sendMessage({
    "message_type": "image",
    "image": {
        "url": "https://example.com/image.jpg"
    }
}).then((event) => {
    console.log("message was sent", event);
}).catch((error)=>{
    console.error("error sending the message", error);
});

// Scenario #2: Upload an image from a file input to Vonage, then send
// Note: the URL will need to be downloaded using the fetch image method mentioned in the next section.
    
const fileInput = document.getElementById('fileInput');
const params = {
    quality_ratio : "90",
    medium_size_ratio: "40",
    thumbnail_size_ratio: "20"
}
conversation.uploadImage(fileInput.files[0], params).then((imageRequest) => {
    imageRequest.onreadystatechange = () => {
        if (imageRequest.readyState === 4 && imageRequest.status === 200) {
            try {
                const { original, medium, thumbnail } = JSON.parse(imageRequest.responseText);
                const message = {
                    message_type: 'image',
                    image: {
                        url: original.url ?? medium.url ?? thumbnail.url
                    }
                }
                return conversation.sendMessage(message);
            } catch (error) {
                console.error("error sending the image", error);
            }
        }
        if (imageRequest.status !== 200) {
            console.error("error uploading the image");
        }
    };
    return imageRequest;
}).catch((error) => {
    console.error("error uploading the image ", error);
});

Receive an Image URL

A message conversation event will be received when a member sends an image to a conversation:

conversation.on('message', (sender, event) => {
  if (event.body.message_type === 'image'){
    console.log('*** Image sender: ', sender);
    console.log('*** Image event: ', event);
  }
});

Download images from Vonage

Web client

To download an image you need you use the fetch image method.

Mobile client (Android, iOS)

To download an image you need to add JWT to the image retrieval request. The JWT is passed as an Authorization header (Authorization: Bearer <JWT> format). This is the JWT that was used to log in the user.

Various image libraries are handling request headers differently, so below you will full example for the most popular libraries. Notice the JWT being set as the Authorization header for the request:

// ==== LOAD IMAGE USING COIL ==== 
// https://github.com/coil-kt/coil
private fun loadImageUsingCoil(url: String, jwt: String, context: Context) {
    imageView.load(
        Uri.parse(url),
        context.imageLoader,
    ) {
        addHeader("Authorization", "bearer $jwt")
    }
}

// ==== LOAD IMAGE USING GLIDE ==== 
// https://github.com/bumptech/glide
private fun loadImageUsingGlide(url: String, jwt: String, context: Context) {
    val build = LazyHeaders.Builder()
        .addHeader("Authorization", "bearer $jwt")
        .build()

    val glideUrl = GlideUrl(url, build)

    Glide.with(context)
        .load(glideUrl)
        .into(imageView)
}

// ==== LOAD IMAGE USING PICASSO ====
// https://github.com/square/picasso

// Define custom Authentication interceptor
class AuthenticationInterceptor(private val jwt: String) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response = chain.request().let {
        val newRequest = it.newBuilder()
            .header("Authorization", "bearer $jwt")
            .build()

        chain.proceed(newRequest)
    }
}

// Create Picasso instance that uses the Authenticator
private fun getPicassoInstance(jwt: String): Picasso {
    val okHttpClient = OkHttpClient.Builder()
        .addInterceptor(AuthenticationInterceptor(jwt))
        .build()

    return Picasso.Builder(requireContext()).downloader(OkHttp3Downloader(okHttpClient)).build()
}

// Load image using custom picasso instance (that under the hood uses the authentication interceptor)
private fun loadImageUsingPicasso(url: String, jwt: String, context: Context) {
    getPicassoInstance(jwt)
        .load(url)
        .into(imageView)
}

Reference