Tutoriel : Activer la prise en charge des images en ligne dans votre application de conversation instantanée
Le SDK Conversation est conçu pour fonctionner de manière fluide avec Microsoft Teams. Plus précisément, le Kit de développement logiciel (SDK) Chat fournit une solution permettant de recevoir des images inline et d’envoyer des images inline aux utilisateurs de Microsoft Teams.
Dans ce didacticiel, vous apprendrez à activer la prise en charge des images en ligne à l’aide du SDK Azure Communication Services Chat pour JavaScript.
Les images en ligne sont des images copiées et collées directement dans la zone d’envoi du client Teams. Pour les images téléchargées via le menu Télécharger à partir de cet appareil ou par glisser-déposer, telles que les images glissées directement vers la boîte d'envoi dans Teams, vous devez vous référer à ce didacticiel dans le cadre de la fonctionnalité de partage de fichiers. (Consultez la section « Gérer les pièces jointes d’image . »)
Pour copier une image, les utilisateurs de Teams ont deux options :
- Utilisez le menu contextuel de leur système d’exploitation pour copier le fichier image, puis collez-le dans la zone d’envoi de son client Teams.
- Utilisez des raccourcis clavier.
Dans ce tutoriel, vous allez découvrir ce que vous devez faire lorsque vous procédez comme suit :
Remarque
La possibilité d'envoyer des images en ligne est actuellement disponible en préversion publique. Il est disponible uniquement pour JavaScript. Pour recevoir des images en ligne, il est actuellement généralement disponible. Il est disponible pour JavaScript et C# dans une conversation d’interopérabilité Teams.
Prérequis
- Passez en revue le guide de démarrage rapide Rejoindre votre application conversation à une réunion Teams.
- Créer une ressource Azure Communication Services. Pour plus d’informations, consultez Créer une ressource Azure Communication Services. Vous devez enregistrer votre chaîne de connexion pour ce tutoriel.
- Configurez une réunion Teams à l’aide de votre compte professionnel et préparez l’URL de la réunion.
- Utilisez le Kit de développement logiciel (SDK) Chat pour JavaScript (@azure/communication-chat) 1.4.0 ou la dernière version. Pour plus d’informations, consultez Bibliothèque cliente Azure Communication Chat pour JavaScript.
Exemple de code
Vous trouverez le code finalisé de ce tutoriel sur GitHub.
Gérer les images en ligne reçues dans un nouvel événement de message
Dans cette section, vous apprendrez comment restituer des images en ligne intégrées dans le contenu du message d'un nouvel événement de message reçu.
Dans le démarrage rapide, vous avez créé un gestionnaire d'événements chatMessageReceived
pour l'événement, qui est déclenché lorsque vous recevez un nouveau message de l'utilisateur Teams. Vous ajoutez également du contenu de message entrant à messageContainer
directement lors de la réception de l’événement de chatMessageReceived
à partir du chatClient
, comme suit :
chatClient.on("chatMessageReceived", (e) => {
console.log("Notification chatMessageReceived!");
// Check whether the notification is intended for the current thread
if (threadIdInput.value != e.threadId) {
return;
}
if (e.sender.communicationUserId != userId) {
renderReceivedMessage(e.message);
}
else {
renderSentMessage(e.message);
}
});
async function renderReceivedMessage(message) {
messages += '<div class="container lighter">' + message + '</div>';
messagesContainer.innerHTML = messages;
}
À partir de l'événement entrant de type ChatMessageReceivedEvent
, une propriété nommée attachments
contient des informations sur l'image en ligne. C'est tout ce dont vous avez besoin pour afficher des images en ligne dans votre interface utilisateur :
export interface ChatMessageReceivedEvent extends BaseChatMessageEvent {
/**
* Content of the message.
*/
message: string;
/**
* Metadata of the message.
*/
metadata: Record<string, string>;
/**
* Chat message attachment.
*/
attachments?: ChatAttachment[];
}
export interface ChatAttachment {
/** Id of the attachment */
id: string;
/** The type of attachment. */
attachmentType: ChatAttachmentType;
/** The name of the attachment content. */
name?: string;
/** The URL where the attachment can be downloaded */
url?: string;
/** The URL where the preview of attachment can be downloaded */
previewUrl?: string;
}
export type ChatAttachmentType = "image" | "unknown";
Revenez maintenant au code précédent pour ajouter une logique supplémentaire, comme les extraits de code suivants :
chatClient.on("chatMessageReceived", (e) => {
console.log("Notification chatMessageReceived!");
// Check whether the notification is intended for the current thread
if (threadIdInput.value != e.threadId) {
return;
}
const isMyMessage = e.sender.communicationUserId === userId;
renderReceivedMessage(e, isMyMessage);
});
function renderReceivedMessage(e, isMyMessage) {
const messageContent = e.message;
const card = document.createElement('div');
card.className = isMyMessage ? "container darker" : "container lighter";
card.innerHTML = messageContent;
messagesContainer.appendChild(card);
// Filter out inline images from attachments
const imageAttachments = e.attachments.filter((e) =>
e.attachmentType.toLowerCase() === 'image');
// Fetch and render preview images
fetchPreviewImages(imageAttachments);
// Set up onclick event handler to fetch full-scale image
setImgHandler(card, imageAttachments);
}
function setImgHandler(element, imageAttachments) {
// Do nothing if there are no image attachments
if (!imageAttachments.length > 0) {
return;
}
const imgs = element.getElementsByTagName('img');
for (const img of imgs) {
img.addEventListener('click', (e) => {
// Fetch full-scale image upon click
fetchFullScaleImage(e, imageAttachments);
});
}
}
async function fetchPreviewImages(attachments) {
if (!attachments.length > 0) {
return;
}
// Since each message could contain more than one inline image
// we need to fetch them individually
const result = await Promise.all(
attachments.map(async (attachment) => {
// Fetch preview image from its 'previewURL'
const response = await fetch(attachment.previewUrl, {
method: 'GET',
headers: {
// The token here should be the same one from chat initialization
'Authorization': 'Bearer ' + tokenString,
},
});
// The response would be in an image blob, so we can render it directly
return {
id: attachment.id,
content: await response.blob(),
};
}),
);
result.forEach((imageResult) => {
const urlCreator = window.URL || window.webkitURL;
const url = urlCreator.createObjectURL(imageResult.content);
// Look up the image ID and replace its 'src' with object URL
document.getElementById(imageResult.id).src = url;
});
}
Dans cet exemple, vous avez créé deux fonctions d’assistance, fetchPreviewImages
et setImgHandler
. La première extrait l’image d’aperçu directement à partir du previewURL
fourni dans chaque objet ChatAttachment
avec un en-tête d’authentification. De même, vous configurez un événement onclick
pour chaque image de la fonction setImgHandler
. Dans le gestionnaire d’événements, vous récupérez une image à l’échelle complète à partir de la propriété url
de l’objet ChatAttachment
avec un en-tête d’authentification.
Vous devez maintenant exposer le jeton au niveau global, car vous devez construire un en-tête d’authentification avec celui-ci. Vous devez modifier le code suivant :
// New variable for token string
var tokenString = '';
async function init() {
....
let tokenResponse = await identityClient.getToken(identityResponse, [
"voip",
"chat"
]);
const { token, expiresOn } = tokenResponse;
// Save to token string
tokenString = token;
...
}
Pour afficher l’image à grande échelle dans une superposition, vous devez également ajouter un nouveau composant :
<div class="overlay" id="overlay-container">
<div class="content">
<img id="full-scale-image" src="" alt="" />
</div>
</div>
Avec des CSS :
/* let's make chat popup scrollable */
.chat-popup {
...
max-height: 650px;
overflow-y: scroll;
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
z-index: 100;
}
.overlay .content {
position: fixed;
width: 100%;
height: 100%;
text-align: center;
overflow: hidden;
z-index: 100;
margin: auto;
background-color: rgba(0, 0, 0, .7);
}
.overlay img {
position: absolute;
display: block;
max-height: 90%;
max-width: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#overlay-container {
display: none
}
Maintenant que vous disposez d’une superposition configurée, il est temps de travailler sur la logique pour afficher des images à grande échelle. Rappelez-vous que vous avez créé un gestionnaire d’événements onClick
pour appeler une fonction fetchFullScaleImage
:
const overlayContainer = document.getElementById('overlay-container');
const loadingImageOverlay = document.getElementById('full-scale-image');
function fetchFullScaleImage(e, imageAttachments) {
// Get the image ID from the clicked image element
const link = imageAttachments.filter((attachment) =>
attachment.id === e.target.id)[0].url;
loadingImageOverlay.src = '';
// Fetch the image
fetch(link, {
method: 'GET',
headers: {'Authorization': 'Bearer ' + tokenString},
}).then(async (result) => {
// Now we set image blob to our overlay element
const content = await result.blob();
const urlCreator = window.URL || window.webkitURL;
const url = urlCreator.createObjectURL(content);
loadingImageOverlay.src = url;
});
// Show overlay
overlayContainer.style.display = 'block';
}
Une dernière chose que vous souhaitez ajouter est la possibilité de ignorer la superposition lorsque l’image est cliqué :
loadingImageOverlay.addEventListener('click', () => {
overlayContainer.style.display = 'none';
});
Vous avez maintenant apporté toutes les modifications nécessaires pour afficher les images en ligne pour les messages provenant de notifications en temps réel.
Exécuter le code
Les utilisateurs de Webpack peuvent l'utiliser webpack-dev-server
pour créer et exécuter votre application. Exécutez la commande suivante pour regrouper votre hôte d’application sur un serveur web local :
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Démo
Ouvrez votre navigateur et accédez àhttp://localhost:8080/
. Saisissez l’URL de la réunion et l’ID du thread. Envoyez des images en ligne depuis le client Teams.
Ensuite, vous devez voir le nouveau message affiché avec les images d’aperçu.
Une fois que l’utilisateur Azure Communication Services sélectionne l’image d’aperçu, une superposition s’affiche avec l’image à grande échelle envoyée par l’utilisateur Teams.
Gérer l'envoi d'images en ligne dans une nouvelle demande de message
Important
Cette fonctionnalité d’Azure Communication Services est actuellement en préversion.
Ces interfaces de programmation d’applications et kits de développement logiciel (SDK) en préversion sont fournis sans contrat au niveau du service. Nous vous recommandons de ne pas les utiliser pour les charges de travail de production. Certaines fonctionnalités peuvent être limitées ou non prises en charge.
Pour plus d’informations, consultez Conditions d’utilisation supplémentaires relatives aux préversions de Microsoft Azure.
En plus de gérer les messages avec des images en ligne, le SDK Chat pour JavaScript fournit également une solution permettant à l'utilisateur de communication d'envoyer des images en ligne à l'utilisateur Microsoft Teams dans une conversation d'interopérabilité.
Examinez la nouvelle API à partir de ChatThreadClient
:
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
"onUploadProgress": reportProgressCallback
});
L’API prend un objet blob d’images, une chaîne de nom de fichier et un rappel de fonction qui signale la progression du chargement.
Pour envoyer une image à un autre participant de conversation, vous devez :
- Chargez l’image via l’API
uploadImage
à partir deChatThreadClient
, puis enregistrez l’objet retourné. - Composez le contenu du message et définissez une pièce jointe sur l’objet retourné que vous avez enregistré à l’étape précédente.
- Envoyez le nouveau message via l'API
sendMessage
deChatThreadClient
.
Créez un sélecteur de fichiers qui accepte des images :
<label for="myfile">Attach images:</label>
<input id="upload" type="file" id="myfile" name="myfile" accept="image/*" multiple>
<input style="display: none;" id="upload-result"></input>
À présent, configurez un écouteur d’événements pour le moment où un changement d’état se produit :
document.getElementById("upload").addEventListener("change", uploadImages);
Vous devez créer une fonction pour le moment où l’état change :
var uploadedImageModels = [];
async function uploadImages(e) {
const files = e.target.files;
if (files.length === 0) {
return;
}
for (let key in files) {
if (files.hasOwnProperty(key)) {
await uploadImage(files[key]);
}
}
}
async function uploadImage(file) {
const buffer = await file.arrayBuffer();
const blob = new Blob([new Uint8Array(buffer)], {type: file.type });
const url = window.URL.createObjectURL(blob);
document.getElementById("upload-result").innerHTML += `<img src="${url}" height="auto" width="100" />`;
let uploadedImageModel = await chatThreadClient.uploadImage(blob, file.name, {
imageBytesLength: file.size
});
uploadedImageModels.push(uploadedImageModel);
}
Dans cet exemple, vous avez créé un FileReader
pour lire chaque image sous base64
- forme d'images codées, puis créez un Blob
avant d'appeler l'API ChatSDK pour les télécharger. Vous avez créé un fichier global uploadedImageModels
pour enregistrer les modèles de données des images téléchargées à partir du SDK Chat.
Enfin, vous devez modifier l’écouteur d’événements sendMessageButton
que vous avez créé précédemment pour attacher les images que vous avez chargées.
sendMessageButton.addEventListener("click", async () => {
let message = messagebox.value;
let attachments = uploadedImageModels;
// Inject image tags for images we have selected
// so they can be treated as inline images
// Alternatively, we can use some third-party libraries
// to have a rich text editor with inline image support
message += attachments.map((attachment) => `<img id="${attachment.id}" />`).join("");
let sendMessageRequest = {
content: message,
attachments: attachments,
};
let sendMessageOptions = {
senderDisplayName: "Jack",
type: "html"
};
let sendChatMessageResult = await chatThreadClient.sendMessage(
sendMessageRequest,
sendMessageOptions
);
let messageId = sendChatMessageResult.id;
uploadedImageModels = [];
messagebox.value = "";
document.getElementById("upload").value = "";
console.log(`Message sent!, message id:${messageId}`);
});
Vous avez terminé. Exécutez maintenant le code pour le voir en action.
Exécuter le code
Les utilisateurs de Webpack peuvent l'utiliser webpack-dev-server
pour créer et exécuter votre application. Exécutez la commande suivante pour regrouper votre hôte d’application sur un serveur web local :
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Démo
Ouvrez votre navigateur et accédez àhttp://localhost:8080/
. Vous disposez d’une nouvelle section dans la zone d’envoi pour joindre des images.
Ensuite, vous pouvez sélectionner les images que vous souhaitez attacher.
L’utilisateur Teams doit maintenant recevoir l’image que vous venez d’envoyer lorsqu’il sélectionne Envoyer.
Ce didacticiel vous montre comment activer la prise en charge des images en ligne à l’aide du SDK Chat Azure Communication Services pour C#.
Dans ce tutoriel, vous allez apprendre à :
- Gérez les images en ligne pour les nouveaux messages.
Prérequis
- Consultez le guide de démarrage rapide Rejoignez votre application de chat à une réunion Teams.
- Créer une ressource Azure Communication Services. Pour plus d’informations, consultez Créer une ressource Azure Communication Services. Vous devez enregistrer votre chaîne de connexion pour ce tutoriel.
- Configurez une réunion Teams à l’aide de votre compte professionnel et préparez l’URL de la réunion.
- Utilisez le kit de développement logiciel (SDK) Chat pour C# (Azure.Communication.Chat) 1.3.0 ou une version plus récente. Pour plus d’informations, consultez Bibliothèque cliente Azure Communication Chat pour .NET.
But
- Saisissez la propriété
previewUri
pour les pièces jointes d’images en ligne.
Gérer les images en ligne des nouveaux messages
Dans le démarrage rapide, vous recherchez des messages et ajoutez de nouveaux messages à la propriété messageList
. Vous développerez cette fonctionnalité ultérieurement pour inclure l'analyse et la récupération des images en ligne.
CommunicationUserIdentifier currentUser = new(user_Id_);
AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
SortedDictionary<long, string> messageList = [];
int textMessages = 0;
await foreach (ChatMessage message in allMessages)
{
if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
{
textMessages++;
var userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
var strippedMessage = StripHtml(message.Content.Message);
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{strippedMessage}");
}
}
À partir de l'événement entrant de type ChatMessageReceivedEvent
, la propriété nommée attachments
contient des informations sur l'image en ligne. C'est tout ce dont vous avez besoin pour restituer des images en ligne dans votre interface utilisateur.
public class ChatAttachment
{
public ChatAttachment(string id, ChatAttachmentType attachmentType)
public ChatAttachmentType AttachmentType { get }
public string Id { get }
public string Name { get }
public System.Uri PreviewUrl { get }
public System.Uri Url { get }
}
public struct ChatAttachmentType : System.IEquatable<AttachmentType>
{
public ChatAttachmentType(string value)
public static File { get }
public static Image { get }
}
Le code JSON suivant est un exemple de ce que ChatAttachment
peut ressembler à une pièce jointe d’image :
"attachments": [
{
"id": "9d89acb2-c4e4-4cab-b94a-7c12a61afe30",
"attachmentType": "image",
"name": "Screenshot.png",
"url": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/original?api-version=2023-11-03",
"previewUrl": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/small?api-version=2023-11-03"
}
]
Revenez en arrière et remplacez le code pour ajouter une logique supplémentaire pour analyser et extraire les pièces jointes de l’image :
CommunicationUserIdentifier currentUser = new(user_Id_);
AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
SortedDictionary<long, string> messageList = [];
int textMessages = 0;
await foreach (ChatMessage message in allMessages)
{
// Get message attachments that are of type 'image'
IEnumerable<ChatAttachment> imageAttachments = message.Content.Attachments.Where(x => x.AttachmentType == ChatAttachmentType.Image);
// Fetch image and render
var chatAttachmentImageUris = new List<Uri>();
foreach (ChatAttachment imageAttachment in imageAttachments)
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", communicationTokenCredential.GetToken().Token);
var response = await client.GetAsync(imageAttachment.PreviewUri);
var randomAccessStream = await response.Content.ReadAsStreamAsync();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(randomAccessStream.AsRandomAccessStream());
InlineImage.Source = bitmapImage;
});
chatAttachmentImageUris.Add(imageAttachment.PreviewUri);
}
// Build message list
if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
{
textMessages++;
var userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
var strippedMessage = StripHtml(message.Content.Message);
var chatAttachments = chatAttachmentImageUris.Count > 0 ? "[Attachments]:\n" + string.Join(",\n", chatAttachmentImageUris) : "";
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{strippedMessage}\n{chatAttachments}");
}
Dans cet exemple, vous récupérez toutes les pièces jointes du message de type Image
, puis récupérez chacune des images. Vous devez utiliser votre Token
dans la partie Bearer
de l'en-tête de la demande à des fins d'autorisation. Une fois l’image téléchargée, vous pouvez l’affecter à l’élément InlineImage
de la vue.
Vous incluez également une liste des URI de pièce jointe à afficher avec le message dans la liste de messages texte.
Démo
- Exécutez l’application à partir de l’environnement de développement intégré (IDE).
- Entrez un lien de réunion Teams.
- Rejoindre la réunion.
- Admettez l’utilisateur côté Teams.
- Envoyez un message du côté Teams avec une image.
L’URL incluse dans le message apparaît dans la liste des messages. La dernière image reçue est affichée en bas de la fenêtre.
Étapes suivantes
- En savoir plus sur les autres fonctionnalités d'interopérabilité prises en charge.
- Consultez notre exemple de héros de chat.
- Apprenez-en davantage sur le fonctionnement de Chat.