Tutorial: Aktivieren der Inline-Bildunterstützung in Ihrer Chat-App
Das Chat SDK ist für die nahtlose Zusammenarbeit mit Microsoft Teams konzipiert. Insbesondere bietet das Chat SDK eine Lösung zum Empfangen und Senden von Inlinebildern von und an Microsoft Teams-Benutzerinnen und -Benutzer.
In diesem Tutorial erfahren Sie, wie Sie die Inlinebildunterstützung mithilfe des Azure Communication Services Chat-SDK für JavaScript aktivieren.
Inlinebilder sind Bilder, die direkt in das Sendefeld des Teams-Clients kopiert und eingefügt werden. Informationen zu Bildern, die über das Menü Von diesem Gerät hochladen oder per Drag-and-Drop hochgeladen wurden, z. B. Bilder, die direkt in das Sendefeld in Teams gezogen wurden, finden Sie in diesem Tutorial als Teil des Dateifreigabefeatures. (Siehe Abschnitt „Verarbeiten von Bildanlagen“.)
Zum Kopieren eines Bildes haben Teams-Benutzer zwei Optionen:
- Sie können das Kontextmenü des Betriebssystems verwenden, um die Bilddatei zu kopieren und sie dann in das Sendefeld des Teams-Clients einzufügen.
- Verwenden von Tastenkombinationen
In diesem Tutorial erfahren Sie, was Sie tun müssen, wenn Sie:
Hinweis
Die Möglichkeit zum Senden von Inlinebildern befindet sich derzeit in der öffentlichen Vorschau. Sie ist nur für JavaScript verfügbar. Für den Empfang von Inlinebildern ist sie derzeit allgemein verfügbar. Sie ist sowohl für JavaScript als auch für C# in einem Teams-Interoperabilitätschat verfügbar.
Voraussetzungen
- Lesen Sie die Schnellstartanleitung Beitreten mit einer Chat-App zu einer Teams-Besprechung.
- Erstellen Sie eine Azure Communication Services-Ressource. Ausführlichere Informationen hierzu finden Sie unter Schnellstart: Erstellen und Verwalten einer Communication Services-Ressource. Für dieses Tutorial müssen Sie Ihre Verbindungszeichenfolge erfassen.
- Richten Sie eine Teams-Besprechung mit Ihrem Geschäftskonto ein, und halten Sie die URL der Besprechung bereit.
- Verwenden Sie das Chat-SDK für JavaScript (@azure/communication-chat) 1.4.0 oder die neueste Version. Weitere Informationen finden Sie unter Azure Communication Chat-Clientbibliothek für JavaScript.
Beispielcode
Den finalen Code dieses Tutorials finden Sie auf GitHub.
Behandeln von empfangenen Inlinebildern in einem Ereignis „Neue Nachricht“
In diesem Abschnitt erfahren Sie, wie Inlinebilder gerendert werden können, die in den Nachrichteninhalt des Ereignisses „Neue Nachricht empfangen“ eingebettet sind.
In der Schnellstartanleitung haben Sie einen Ereignishandler für das Ereignis chatMessageReceived
erstellt, der ausgelöst wird, wenn Sie eine neue Nachricht vom Teams-Benutzer erhalten. Sie haben auch den Inhalt der eingehenden Nachricht direkt an messageContainer
angefügt, nachdem das Ereignis chatMessageReceived
vom chatClient
empfangen wurde, wie hier gezeigt:
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;
}
Aus dem eingehenden Ereignis vom Typ ChatMessageReceivedEvent
enthält eine Eigenschaft mit dem Namen attachments
Informationen zum Inlinebild. Das ist alles, was Sie benötigen, um Inlinebilder in Ihrer Benutzeroberfläche zu rendern:
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";
Kehren Sie nun zum vorherigen Code zurück, um zusätzliche Logik wie die folgenden Codeschnipsel hinzuzufügen:
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;
});
}
In diesem Beispiel haben Sie zwei Hilfsfunktionen erstellt: fetchPreviewImages
und setImgHandler
. Die erste ruft das Vorschaubild direkt aus der previewURL
ab, die in jedem ChatAttachment
-Objekt mit einem Authentifizierungsheader bereitgestellt wird. Ebenso richten Sie ein onclick
-Ereignis für jedes Bild in der setImgHandler
-Funktion ein. Im Ereignishandler rufen Sie ein Bild mit voller Skalierung aus der Eigenschaft url
aus dem ChatAttachment
-Objekt mit einem Authentifizierungsheader ab.
Nun müssen Sie das Token auf globaler Ebene verfügbar machen, da Sie damit einen Authentifizierungsheader erstellen müssen. Sie müssen den folgenden Code ändern:
// 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;
...
}
Um das Bild in vollständiger Skalierung in einer Überlagerung anzuzeigen, müssen Sie auch eine neue Komponente hinzufügen:
<div class="overlay" id="overlay-container">
<div class="content">
<img id="full-scale-image" src="" alt="" />
</div>
</div>
Mit etwas 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
}
Nachdem Sie nun eine Überlagerung eingerichtet haben, arbeiten Sie jetzt an der Logik zum Rendern von Bildern in vollständiger Skalierung. Zur Erinnerung: Sie haben einen onClick
-Ereignishandler erstellt, um eine fetchFullScaleImage
-Funktion aufzurufen:
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';
}
Als Letztes möchten Sie die Möglichkeit hinzufügen, die Überlagerung beim Klicken auf das Bild zu schließen:
loadingImageOverlay.addEventListener('click', () => {
overlayContainer.style.display = 'none';
});
Jetzt haben Sie alle Änderungen vorgenommen, die zum Rendern von Inlinebildern für Nachrichten aus Echtzeitbenachrichtigungen erforderlich sind.
Ausführen des Codes
Webpack-Benutzer können webpack-dev-server
verwenden, um Ihre App zu erstellen und auszuführen. Führen Sie den folgenden Befehl aus, um Ihren Anwendungshost auf einem lokalen Webserver zu bündeln:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demo
Öffnen Sie Ihren Browser, und wechseln Sie zuhttp://localhost:8080/
. Geben Sie die Besprechungs-URL und die Thread-ID ein. Senden Sie einige Inlinebilder vom Teams-Client.
Anschließend sollten Sie sehen, wie die neue Nachricht zusammen mit Vorschaubildern gerendert wird.
Nachdem der Azure Communication Services-Benutzer das Vorschaubild ausgewählt hat, wird eine Überlagerung mit dem Bild in vollständiger Skalierung angezeigt, das vom Teams-Benutzer gesendet wurde.
Behandeln des Sendens von Inlinebildern in einer Anforderung „Neue Nachricht“
Wichtig
Dieses Feature von Azure Communication Services befindet sich derzeit in der Vorschau.
Vorschau-APIs und -SDKs werden ohne Vereinbarung zum Servicelevel bereitgestellt. Es wird empfohlen, diese nicht für Produktionsworkloads zu verwenden. Einige Features werden möglicherweise nicht unterstützt oder bieten nur eingeschränkte Funktionalität.
Weitere Informationen finden Sie in den ergänzenden Nutzungsbestimmungen für Microsoft Azure-Vorschauversionen.
Zusätzlich zur Handhabung von Nachrichten mit Inlinebildern bietet das Chat-SDK für JavaScript auch eine Lösung, die es dem Kommunikationsbenutzer ermöglicht, Inlinebilder an die Microsoft Teams-Benutzer in einem Interoperabilitätschat zu senden.
Sehen Sie sich die neue API vom ChatThreadClient
an:
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
"onUploadProgress": reportProgressCallback
});
Die API erfasst einen Bild-Blob, eine Zeichenkette mit dem Dateinamen und einen Funktionsrückruf, der den Fortschritt des Uploads meldet.
Um ein Bild an andere Chat-Teilnehmende zu senden, müssen Sie folgende Schritte ausführen:
- Laden Sie das Bild über die
uploadImage
-API vomChatThreadClient
hoch, und speichern Sie das zurückgegebene Objekt. - Verfassen Sie den Nachrichteninhalt, und legen Sie die Anlage auf das zurückgegebene Objekt fest, das Sie im vorherigen Schritt gespeichert haben.
- Senden Sie die neue Nachricht über die
sendMessage
-API vomChatThreadClient
.
Erstellen Sie eine neue Dateiauswahl, die Bilder akzeptiert:
<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>
Richten Sie nun einen Ereignislistener für den Fall einer Statusänderung ein:
document.getElementById("upload").addEventListener("change", uploadImages);
Sie müssen eine neue Funktion für eine Statusänderung erstellen:
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);
}
In diesem Beispiel haben Sie einen FileReader
erstellt, um jedes Bild als base64
-kodierte Bilder zu lesen. Dann wird ein Blob
erstellt, bevor die ChatSDK-API aufgerufen wird, um sie hochzuladen. Sie haben eine globale uploadedImageModels
erstellt, um die Datenmodelle hochgeladener Bilder aus dem Chat-SDK zu speichern.
Zuletzt müssen Sie den zuvor erstellten sendMessageButton
-Ereignislistener ändern, um die hochgeladenen Bilder anzufügen.
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}`);
});
Das ist alles. Führen Sie nun den Code aus, um ihn in Aktion zu sehen.
Ausführen des Codes
Webpack-Benutzer können webpack-dev-server
verwenden, um Ihre App zu erstellen und auszuführen. Führen Sie den folgenden Befehl aus, um Ihren Anwendungshost auf einem lokalen Webserver zu bündeln:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demo
Öffnen Sie Ihren Browser, und wechseln Sie zuhttp://localhost:8080/
. Im Sendefeld befindet sich ein neuer Bereich zum Anfügen von Bildern.
Als Nächstes können Sie die Bilder auswählen, die Sie anfügen möchten.
Der Teams-Benutzer sollte nun das Bild erhalten, das Sie gerade gesendet haben, wenn er Senden auswählt.
In diesem Tutorial erfahren Sie, wie Sie die Inlinebildunterstützung mit dem Azure Communication Services Chat-SDK für C# aktivieren.
In diesem Tutorial lernen Sie Folgendes:
- Behandeln Sie Inlinebilder für neue Nachrichten.
Voraussetzungen
- Lesen Sie die Schnellstartanleitung Beitreten mit einer Chat-App zu einer Teams-Besprechung.
- Erstellen Sie eine Azure Communication Services-Ressource. Ausführlichere Informationen hierzu finden Sie unter Schnellstart: Erstellen und Verwalten einer Communication Services-Ressource. Für dieses Tutorial müssen Sie Ihre Verbindungszeichenfolge erfassen.
- Richten Sie eine Teams-Besprechung mit Ihrem Geschäftskonto ein, und halten Sie die URL der Besprechung bereit.
- Verwenden Sie das Chat SDK für C# (Azure.Communication.Chat) 1.3.0 oder die neueste Version. Weitere Informationen finden Sie unter Azure Communication Chat-Clientbibliothek für .NET.
Ziel
- Verwenden Sie die
previewUri
-Eigenschaft für Inlinebildanlagen.
Behandeln von Inlinebildern für neue Nachrichten
In der Schnellstartanleitung fragen Sie Nachrichten ab und fügen neue Nachrichten an die messageList
-Eigenschaft an. Sie bauen später auf dieser Funktionalität auf, um das Parsen und Abrufen der Inlinebilder zu ermöglichen.
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}");
}
}
Aus dem eingehenden Ereignis vom Typ ChatMessageReceivedEvent
enthält die Eigenschaft mit dem Namen attachments
Informationen zum Inlinebild. Das ist alles, was Sie benötigen, um Inlinebilder in Ihrer Benutzeroberfläche zu rendern.
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 }
}
Der folgende JSON-Code ist ein Beispiel dafür, wie ChatAttachment
für eine Bildanlage aussehen könnte:
"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"
}
]
Gehen Sie nun zurück, und ersetzen Sie den Code, um zusätzliche Logik zum Parsen und Abrufen der Bildanlagen hinzuzufügen:
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}");
}
In diesem Beispiel erfassen Sie alle Anlagen vom Typ Image
der Nachricht. Dann rufen Sie die einzelnen Bilder ab. Sie müssen Ihr Token
im Bearer
-Teil des Anforderungsheaders zur Autorisierung verwenden. Nachdem das Bild heruntergeladen wurde, können Sie es dem InlineImage
-Element der Ansicht zuweisen.
Außerdem schließen Sie eine Liste der Anlagen-URIs ein, die zusammen mit der Nachricht in der Textnachrichtenliste angezeigt werden sollen.
Demo
- Führen Sie die Anwendung in der integrierten Entwicklungsumgebung (IDE) aus.
- Geben Sie einen Teams-Besprechungslink ein.
- Der-Besprechung beitreten.
- Lassen Sie den Benutzer in Teams zu.
- Senden Sie eine Nachricht in Teams mit einem Bild.
Die in der Nachricht enthaltene URL wird in der Nachrichtenliste angezeigt. Das zuletzt empfangene Bild wird am unteren Rand des Fensters gerendert.
Nächste Schritte
- Erfahren Sie mehr zu anderen unterstützten Interoperabilitätsfeatures.
- Sehen Sie sich unser Chat-Hero-Beispiel an.
- Erfahren Sie mehr über die Chat-Funktionsweise.