Tutoriel : Activez la prise en charge des pièces jointes dans votre application Chat
Le kit de développement logiciel (SDK) Chat fonctionne en toute transparence avec Microsoft Teams dans le contexte d'une réunion. Seul un utilisateur Teams peut envoyer des pièces jointes à un utilisateur Azure Communication Services. Un utilisateur Azure Communication Services ne peut pas envoyer de fichiers joints à un utilisateur Teams. Pour connaître les fonctionnalités actuelles, consultez Conversation d’interopérabilité Teams.
Ajoutez la prise en charge des pièces jointes de fichiers
Le kit SDK Chat fournit la propriété previewUrl
pour chaque fichier joint. Plus précisément, previewUrl
pointe vers une page web sur SharePoint, où l’utilisateur peut voir le contenu du fichier, le modifier et le télécharger s’il dispose de l’autorisation nécessaire.
Certaines contraintes sont associées à cette fonctionnalité :
l'administrateur Teams de l'abonné de l'expéditeur peut imposer des stratégies qui limitent ou désactivent entièrement cette fonctionnalité. Par exemple, l’administrateur Teams peut désactiver certaines autorisations (notamment
Anyone
), ce qui peut rendre l’URL de fichier joint (previewUrl
) inaccessible.Nous ne prenons en charge que deux autorisations de fichiers :
Anyone
People you choose
(avec l’adresse e-mail)
Informez vos utilisateurs Teams qu’aucune des autres autorisations (par exemple
People in your organization
) n’est prise en charge. Les utilisateurs Teams doivent vérifier que l’autorisation par défaut est prise en charge, une fois qu’ils ont chargé le fichier sur leur client Teams.L'URL de téléchargement direct (
url
) n'est pas prise en charge.
En plus des fichiers classiques (avec le AttachmentType
file
), le kit SDK Chat fournit également la propriété AttachmentType
image
. Les utilisateurs Azure Communication Services peuvent joindre des images d’une manière qui ressemble au comportement du client Microsoft Teams, quand il convertit les images jointes en images incluses au niveau de la couche d’IU. Pour plus d'informations, consultez Gérer les pièces jointes d'image.
Les utilisateurs Azure Communication Services peuvent ajouter des images via l’option Charger à partir de cet appareil, qui s’affiche côté Teams, et le kit SDK Chat retourne ces pièces jointes en tant que image
. Pour les images chargées via Joindre des fichiers cloud, les images sont traitées comme des fichiers classiques côté Teams. Ainsi, le kit SDK Chat retourne les pièces jointes en tant que file
.
Notez également que les utilisateurs Azure Communication Services peuvent uniquement charger des fichiers par glisser-déplacer ou via les commandes de menu relatives aux pièces jointes, Charger à partir de cet appareil et Joindre des fichiers cloud. Certains types de messages avec des médias incorporés (notamment des clips vidéo, des messages audio et des cartes météorologiques) ne sont actuellement pas pris en charge.
Ce tutoriel explique comment activer la prise en charge des fichiers joints à l’aide du kit SDK Azure Communication Services Chat pour JavaScript.
Exemple de code
Vous trouverez le code finalisé de ce tutoriel sur GitHub.
Prérequis
- Passez en revue le guide de démarrage rapide Joindre votre application de 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 SDK Chat pour JavaScript (@azure/communication-chat) 1.5.0, ou la version la plus récente. Pour plus d’informations, consultez Bibliothèque de client Azure Communication Chat pour JavaScript.
Objectifs
- Afficher la pièce jointe dans le thread du message. Chaque carte de fichier joint possède un bouton Ouvrir.
- Afficher les pièces jointes sous forme d'images incluses.
Gérez les pièces jointes de fichiers
Le kit SDK Chat pour JavaScript retourne une propriété ChatAttachmentType
file
pour les fichiers joints classiques, et image
pour les images incluses dans les messages.
export interface ChatMessageReceivedEvent extends BaseChatMessageEvent {
/**
* Content of the message.
*/
message: string;
/**
* Chat message attachment.
*/
attachments?: ChatAttachment[];
...
}
export interface ChatAttachment {
/** Id of the attachment */
id: string;
/** The type of attachment. */
attachmentType: AttachmentType;
/** The name of the attachment content. */
name?: string;
/** The URL that is used to provide the original size of the inline images */
url?: string;
/** The URL that provides the preview of the attachment */
previewUrl?: string;
}
/** Type of supported attachments. */
export type ChatAttachmentType = "image" | "file" | "unknown";
Par exemple, le JSON suivant montre ce à quoi ChatAttachment
pourrait ressembler pour une pièce jointe image et une pièce jointe fichier :
"attachments": [
{
"id": "08a182fe-0b29-443e-8d7f-8896bc1908a2",
"attachmentType": "file",
"name": "business report.pdf",
"previewUrl": "https://contoso.sharepoint.com/:u:/g/user/h8jTwB0Zl1AY"
},
{
"id": "9d89acb2-c4e4-4cab-b94a-7c12a61afe30",
"attachmentType": "image",
"name": "Screenshot.png",
"url": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/messages/123/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/original?api-version=2023-11-15-preview",
"previewUrl": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/messages/123/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/small?api-version=2023-11-15-preview"
}
]
Revenons à présent au gestionnaire d’événements que vous avez créé dans Démarrage rapide : Joindre votre application de conversation à une réunion Teams, et ajoutons une logique supplémentaire pour gérer les pièces jointes avec la propriété attachmentType
file
:
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);
} else {
renderSentMessage(e.message);
}
});
async function renderReceivedMessage(event) {
messages += `<div class="container lighter"> ${event.message} </div>`;
messagesContainer.innerHTML = messages;
// Get the list of attachments and calls renderFileAttachments to construct a file attachment card
var attachmentHtml = event.attachments
.filter(attachment => attachment.attachmentType === "file")
.map(attachment => renderFileAttachments(attachment))
.join('');
messagesContainer.innerHTML += attachmentHtml;
}
function renderFileAttachments(attachment) {
var re = /(?:\.([^.]+))?$/;
var fileExtension = re.exec(attachment.name)[1];
return '<div class="attachment-container">' +
'<img class="attachment-icon" alt="attachment file icon" />' +
'<div>' +
'<p class="attachment-type">' + fileExtension + '</p>' +
'<p>' + attachment.name + '</p>' +
'<a href=' + attachment.previewUrl + ' target="_blank" rel="noreferrer">Open</a>' +
'</div>' +
'</div>';
}
Veillez à ajouter du code CSS pour la carte de pièce jointe :
/* Let's make the chat popup scrollable */
.chat-popup {
...
max-height: 650px;
overflow-y: scroll;
}
.attachment-container {
overflow: hidden;
background: #f3f2f1;
padding: 20px;
margin: 0;
border-radius: 10px;
}
.attachment-container img {
width: 50px;
height: 50px;
float: left;
margin: 0;
}
.attachment-container p {
font-weight: 700;
margin: 0 5px 20px 0;
}
.attachment-container {
display: grid;
grid-template-columns: 100px 1fr;
margin-top: 5px;
}
.attachment-icon {
content: url("data:image/svg+xml;base64, ...");
}
.attachment-container a {
background-color: #dadada;
color: black;
font-size: 12px;
padding: 10px;
border: none;
cursor: pointer;
border-radius: 5px;
text-align: center;
margin-right: 10px;
text-decoration: none;
margin-top: 10px;
}
.attachment-container a:hover {
background-color: black;
color: white;
}
.attachment-type {
position: absolute;
color: black;
border: 2px solid black;
background-color: white;
margin-top: 50px;
font-family: sans-serif;
font-weight: 400;
padding: 2px;
text-transform: uppercase;
font-size: 8px;
}
C’est tout ce dont vous avez besoin pour gérer les fichiers joints. Exécutons ensuite le code.
Exécuter le code
Pour webpack, vous pouvez utiliser la propriété webpack-dev-server
afin de générer et d’exécuter votre application. Exécutez la commande suivante pour préparer un pack de 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
Ou :
npm start
Démonstration de pièce jointe de fichier
Ouvrez votre navigateur et accédez à
http://localhost:8080/
. Saisissez l’URL de la réunion et l’ID du thread.Envoyez des fichiers joints à partir du client Teams.
Vous devez voir le nouveau message s’afficher avec les fichiers joints.
Gérez les pièces jointes d’images
Les pièces jointes d'image doivent être traitées différemment des pièces jointes standard file
. Les images jointes ont la propriété attachmentType
image
, ce qui nécessite l’utilisation du jeton de communication pour récupérer l’aperçu ou les images en taille réelle.
Avant de continuer, suivez le tutoriel montrant comment activer la prise en charge des images incluses dans votre application de conversation. Ce tutoriel explique comment extraire des images qui nécessitent un jeton de communication dans l'en-tête de demande. Une fois que vous avez reçu l’objet blob de type image, vous devez créer une propriété ObjectUrl
, qui pointe vers cet objet blob. Vous injectez ensuite cette URL dans l’attribut src
de chaque image incluse.
Vous savez à présent comment fonctionnent les images incluses, vous pouvez donc afficher les images jointes en tant qu’images incluses classiques.
Tout d'abord, injectez une balise image
dans le contenu du message chaque fois qu'il y a une image en pièce jointe :
async function renderReceivedMessage(event) {
messages += `<div class="container lighter"> ${event.message} </div>`;
messagesContainer.innerHTML = messages;
console.log(event);
// Filter out inline images from attachments
const imageAttachments = event.attachments?.filter(
(attachment) =>
attachment.attachmentType === "image" && !messages.includes(attachment.id)
);
// Inject image tag for all image attachments
var imageAttachmentHtml =
imageAttachments
.map((attachment) => renderImageAttachments(attachment))
.join("") ?? "";
messagesContainer.innerHTML += imageAttachmentHtml;
// Get list of attachments and calls renderFileAttachments to construct a file attachment card
var attachmentHtml =
event.attachments
?.filter((attachment) => attachment.attachmentType === "file")
.map((attachment) => renderFileAttachments(attachment))
.join("") ?? "";
messagesContainer.innerHTML += attachmentHtml;
// Fetch and render preview images
fetchPreviewImages(imageAttachments);
}
function renderImageAttachments(attachment) {
return `<img alt="image" src="" itemscope="png" id="${attachment.id}" style="max-width: 100px">`
}
À présent, empruntons la fonction fetchPreviewImages()
au Tutoriel : Activer la prise en charge des images incluses, et utilisons-la en l’état, sans aucun changement :
function fetchPreviewImages(attachments) {
if (!attachments.length > 0) {
return;
}
Promise.all(
attachments.map(async (attachment) => {
const response = await fetch(attachment.previewUrl, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + tokenString,
},
});
return {
id: attachment.id,
content: await response.blob(),
};
}),
).then((result) => {
result.forEach((imageRef) => {
const urlCreator = window.URL || window.webkitURL;
const url = urlCreator.createObjectURL(imageRef.content);
document.getElementById(imageRef.id).src = url;
});
}).catch((e) => {
console.log('error fetching preview images');
});
}
Cette fonction a besoin d’une propriété tokenString
. Vous devez donc disposer d’une copie globale initialisée dans init()
, comme le montre l’extrait de code suivant :
var tokenString = '';
async function init() {
...
const {
token,
expiresOn
} = tokenResponse;
tokenString = token;
...
}
Vous disposez à présent d'un support pour les pièces jointes aux images. Continuez à exécuter le code et à le voir en action.
Démonstration de pièce jointe d’image
Envoyez des images jointes à partir du client Teams.
Une fois que vous avez envoyé l’image jointe, notez qu’elle devient une image incluse du côté du client Teams.
Retournez à l’exemple d’application, puis vérifiez que la même image est affichée.
Ce tutoriel explique comment activer la prise en charge des fichiers joints à l’aide du kit SDK Azure Communication Services Chat pour C#.
Dans ce tutoriel, vous allez apprendre à :
- Gérer les fichiers joints.
- Gérer les images jointes.
Prérequis
- Passez en revue le guide de démarrage rapide Joindre votre application de conversation à une réunion Teams.
- Créez une ressource Azure Communication Services comme décrit dans 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.
- Téléchargez le kit de développement logiciel (SDK) Chat pour C# (@azure/communication-chat) 1.3.0 ou la version la plus récente. Pour plus d’informations, consultez Bibliothèque de client Azure Communication Chat.
Exemple de code
Recherchez le code finalisé pour ce tutoriel sur GitHub.
Gérez les pièces jointes de fichiers
Le kit SDK Chat pour C# retourne une propriété ChatAttachmentType
file
pour les fichiers joints classiques, et image
pour les images incluses.
public readonly partial struct ChatAttachmentType : IEquatable<ChatAttachmentType>
{
private const string ImageValue = "image";
private const string FileValue = "file";
/// <summary> image. </summary>
public static ChatAttachmentType Image { get; } = new ChatAttachmentType(ImageValue);
/// <summary> file. </summary>
public static ChatAttachmentType File { get; } = new ChatAttachmentType(FileValue);
}
Par exemple, le code JSON suivant montre à quoi peut ressembler ChatAttachment
pour une image jointe et un fichier joint quand vous recevez des requêtes côté serveur :
"attachments": [
{
"id": "08a182fe-0b29-443e-8d7f-8896bc1908a2",
"attachmentType": "file",
"name": "business report.pdf",
"previewUrl": "https://contoso.sharepoint.com/:u:/g/user/h8jTwB0Zl1AY"
},
{
"id": "9d89acb2-c4e4-4cab-b94a-7c12a61afe30",
"attachmentType": "image",
"name": "Screenshot.png",
"url": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/messages/123/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/original?api-version=2023-11-15-preview",
"previewUrl": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/messages/123/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/small?api-version=2023-11-15-preview"
}
]
Revenez à présent au gestionnaire d’événements que vous avez créé dans le guide de démarrage rapide précédent, puis ajoutez une logique supplémentaire pour gérer les pièces jointes avec la propriété ChatAttachmentType
file
:
await foreach (ChatMessage message in allMessages)
{
// Get message attachments that are of type 'file'
IEnumerable<ChatAttachment> fileAttachments = message.Content.Attachments.Where(x => x.AttachmentType == ChatAttachmentType.File);
var chatAttachmentFileUris = new List<Uri>();
foreach (var file in fileAttachments)
{
chatAttachmentFileUris.Add(file.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 = fileAttachments.Count() > 0 ? "[Attachments]:\n" + string.Join(",\n", chatAttachmentFileUris) : "";
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{strippedMessage}\n{chatAttachments}");
}
}
Plus précisément, pour chaque fichier joint, vous obtenez la propriété previewUrl
, et vous construisez une liste d’URL dans for loop
. Vous incorporez ensuite la chaîne dans le contenu du message de conversation.
Gérez les pièces jointes d’images
Vous devez gérer les pièces jointes de type image différemment des pièces jointes file
standard. Les images jointes ont la propriété ChatAttachmentType
image
, ce qui nécessite l’utilisation du jeton de communication pour récupérer l’aperçu ou les images en taille réelle.
Avant de continuer, terminez le tutoriel Activer la prise en charge des images incluses. Pour identifier les images jointes, vous devez déterminer si le contenu du message contient le même ID d’image que les pièces jointes.
bool isImageAttachment = message.Content.Message.Contains(x.Id);
Si cet indicateur a la valeur true, vous appliquez la logique de l’image incluse pour l’afficher :
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);
}
Votre application prend désormais en charge les pièces jointes d'images.
Étapes suivantes
- Découvrez plus en détail comment activer la prise en charge des images incluses.
- Découvrez plus en détail les autres fonctionnalités d’interopérabilité prises en charge.
- Consultez notre exemple de conversation de référence.
- Découvrez plus en détail le fonctionnement de la conversation.