Samouczek: włączanie obsługi obrazów wbudowanych w aplikacji Czat
Zestaw SDK czatu został zaprojektowany do bezproblemowej pracy z usługą Microsoft Teams. Zestaw SDK czatu udostępnia rozwiązanie do odbierania obrazów wbudowanych i wysyłania obrazów wbudowanych do użytkowników z usługi Microsoft Teams.
Z tego samouczka dowiesz się, jak włączyć obsługę obrazów wbudowanych przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka JavaScript.
Obrazy wbudowane to obrazy, które są kopiowane i wklejane bezpośrednio w polu wysyłania klienta usługi Teams. W przypadku obrazów przekazanych za pośrednictwem menu Przekaż z tego urządzenia lub przeciągania i upuszczania, takich jak obrazy przeciągane bezpośrednio do pola wysyłania w usłudze Teams, należy odwołać się do tego samouczka w ramach funkcji udostępniania plików. (Zobacz sekcję "Obsługa załączników obrazów").
Aby skopiować obraz, użytkownicy usługi Teams mają dwie opcje:
- Użyj menu kontekstowego systemu operacyjnego, aby skopiować plik obrazu, a następnie wkleić go do pola wysyłania klienta usługi Teams.
- Użyj skrótów klawiaturowych.
Z tego samouczka dowiesz się, co należy zrobić, gdy:
Uwaga
Możliwość wysyłania obrazów wbudowanych jest obecnie dostępna w publicznej wersji zapoznawczej. Jest ona dostępna tylko dla języka JavaScript. W przypadku odbierania obrazów wbudowanych jest ona obecnie ogólnie dostępna. Jest ona dostępna zarówno dla języków JavaScript, jak i C# w czacie współdziałania usługi Teams.
Wymagania wstępne
- Zapoznaj się z przewodnikiem Szybki start Dołącz do aplikacji Czat do spotkania usługi Teams.
- Utwórz zasób usług Azure Communication Services. Aby uzyskać więcej informacji, zobacz Tworzenie zasobu usług Azure Communication Services. Musisz zarejestrować parametry połączenia na potrzeby tego samouczka.
- Skonfiguruj spotkanie usługi Teams przy użyciu konta biznesowego i przygotuj adres URL spotkania.
- Użyj zestawu SDK czatu dla języka JavaScript (@azure/communication-chat) w wersji 1.4.0 lub najnowszej. Aby uzyskać więcej informacji, zobacz Biblioteka klienta czatu usługi Azure Communication dla języka JavaScript.
Przykładowy kod
Znajdź sfinalizowany kod tego samouczka w witrynie GitHub.
Obsługa odebranych obrazów wbudowanych w nowym zdarzeniu wiadomości
W tej sekcji dowiesz się, jak renderować obrazy wbudowane osadzone w zawartości komunikatu nowego zdarzenia odebranego komunikatu.
W przewodniku Szybki start utworzono procedurę obsługi zdarzeń dla chatMessageReceived
zdarzenia, która jest wyzwalana po otrzymaniu nowego komunikatu od użytkownika usługi Teams. Dołączasz również zawartość wiadomości przychodzących bezpośrednio messageContainer
po odebraniu chatMessageReceived
zdarzenia z obiektu chatClient
, w następujący sposób:
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;
}
Z przychodzącego zdarzenia typu ChatMessageReceivedEvent
właściwość o nazwie attachments
zawiera informacje o obrazie wbudowanym. Wystarczy renderować obrazy wbudowane w interfejsie użytkownika:
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";
Teraz wróć do poprzedniego kodu, aby dodać dodatkową logikę, na przykład następujące fragmenty kodu:
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;
});
}
W tym przykładzie utworzono dwie funkcje pomocnicze i fetchPreviewImages
setImgHandler
. Pierwszy pobiera obraz podglądu bezpośrednio z podanego previewURL
w każdym ChatAttachment
obiekcie z nagłówkiem uwierzytelniania. Podobnie skonfigurujesz onclick
zdarzenie dla każdego obrazu w funkcji setImgHandler
. W procedurze obsługi zdarzeń pobierasz obraz o pełnej skali z właściwości url
z ChatAttachment
obiektu z nagłówkiem uwierzytelniania.
Teraz musisz uwidocznić token na poziomie globalnym, ponieważ musisz utworzyć z nim nagłówek uwierzytelniania. Należy zmodyfikować następujący kod:
// 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;
...
}
Aby wyświetlić obraz o pełnej skali w nakładce, należy również dodać nowy składnik:
<div class="overlay" id="overlay-container">
<div class="content">
<img id="full-scale-image" src="" alt="" />
</div>
</div>
Za pomocą niektórych arkuszy 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
}
Teraz, gdy masz już skonfigurowaną nakładkę, nadszedł czas, aby pracować nad logiką w celu renderowania obrazów w pełnej skali. Pamiętaj, że utworzono procedurę obsługi zdarzeń onClick
w celu wywołania funkcji 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';
}
Ostatnią rzeczą, którą chcesz dodać, jest możliwość odrzucenia nakładki po kliknięciu obrazu:
loadingImageOverlay.addEventListener('click', () => {
overlayContainer.style.display = 'none';
});
Teraz wprowadzono wszystkie zmiany, które należy renderować w tekście obrazów dla komunikatów pochodzących z powiadomień w czasie rzeczywistym.
Uruchamianie kodu
Użytkownicy pakietu webpack mogą używać webpack-dev-server
do kompilowania i uruchamiania aplikacji. Uruchom następujące polecenie, aby utworzyć pakiet hosta aplikacji na lokalnym serwerze internetowym:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demonstracja
Otwórz przeglądarkę i przejdź do http://localhost:8080/
. Wprowadź adres URL spotkania i identyfikator wątku. Wyślij kilka wbudowanych obrazów z klienta usługi Teams.
Następnie powinien zostać wyświetlony nowy komunikat renderowany wraz z obrazami podglądu.
Po wybraniu obrazu w wersji zapoznawczej przez użytkownika usług Azure Communication Services zostanie wyświetlona nakładka z obrazem pełnoskalowym wysłanym przez użytkownika usługi Teams.
Obsługa wysyłania obrazów wbudowanych w nowym żądaniu wiadomości
Ważne
Ta funkcja usług Azure Communication Services jest obecnie dostępna w wersji zapoznawczej.
Interfejsy API i zestawy SDK w wersji zapoznawczej są udostępniane bez umowy dotyczącej poziomu usług. Zalecamy, aby nie używać ich w przypadku obciążeń produkcyjnych. Niektóre funkcje mogą nie być obsługiwane lub mogą mieć ograniczone możliwości.
Aby uzyskać więcej informacji, zapoznaj się z dodatkowymi warunkami użytkowania dla wersji zapoznawczych platformy Microsoft Azure.
Oprócz obsługi komunikatów przy użyciu obrazów wbudowanych zestaw Chat SDK dla języka JavaScript udostępnia również rozwiązanie umożliwiające użytkownikowi komunikacji wysyłanie obrazów wbudowanych do użytkownika aplikacji Microsoft Teams w czacie współdziałania.
Zapoznaj się z nowym interfejsem API z witryny ChatThreadClient
:
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
"onUploadProgress": reportProgressCallback
});
Interfejs API przyjmuje obiekt blob obrazu, ciąg nazwy pliku i wywołanie zwrotne funkcji, które zgłasza postęp przekazywania.
Aby wysłać obraz do innego uczestnika czatu, musisz:
- Przekaż obraz za pośrednictwem interfejsu
uploadImage
API zChatThreadClient
pliku i zapisz zwrócony obiekt. - Utwórz zawartość wiadomości i ustaw załącznik na zwrócony obiekt zapisany w poprzednim kroku.
- Wyślij nową wiadomość za pośrednictwem interfejsu
sendMessage
API z adresuChatThreadClient
.
Utwórz nowy selektor plików, który akceptuje obrazy:
<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>
Teraz skonfiguruj odbiornik zdarzeń pod kątem zmiany stanu:
document.getElementById("upload").addEventListener("change", uploadImages);
Podczas zmiany stanu należy utworzyć nową funkcję:
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);
}
W tym przykładzie utworzono element , FileReader
aby odczytać każdy obraz jako obrazy zakodowane w base64
formacie , a następnie utworzyć Blob
element przed wywołaniem interfejsu API ChatSDK w celu ich przekazania. Utworzono globalny model uploadedImageModels
zapisywania modeli danych przekazanych obrazów z zestawu Chat SDK.
Na koniec należy zmodyfikować sendMessageButton
utworzony wcześniej odbiornik zdarzeń, aby dołączyć przekazane obrazy.
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}`);
});
To wszystko. Teraz uruchom kod, aby zobaczyć go w działaniu.
Uruchamianie kodu
Użytkownicy pakietu webpack mogą używać webpack-dev-server
do kompilowania i uruchamiania aplikacji. Uruchom następujące polecenie, aby utworzyć pakiet hosta aplikacji na lokalnym serwerze internetowym:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demonstracja
Otwórz przeglądarkę i przejdź do http://localhost:8080/
. W polu wysyłania masz nową sekcję w celu dołączenia obrazów.
Następnie możesz wybrać obrazy, które chcesz dołączyć.
Użytkownik usługi Teams powinien teraz otrzymać właśnie wysłany obraz po wybraniu pozycji Wyślij.
W tym samouczku pokazano, jak włączyć obsługę obrazów wbudowanych przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka C#.
Z tego samouczka dowiesz się, jak wykonywać następujące czynności:
- Obsługa obrazów wbudowanych dla nowych komunikatów.
Wymagania wstępne
- Zapoznaj się z przewodnikiem Szybki start Dołączanie aplikacji czatu do spotkania w usłudze Teams.
- Utwórz zasób usług Azure Communication Services. Aby uzyskać więcej informacji, zobacz Tworzenie zasobu usług Azure Communication Services. Musisz zarejestrować parametry połączenia na potrzeby tego samouczka.
- Skonfiguruj spotkanie usługi Teams przy użyciu konta biznesowego i przygotuj adres URL spotkania.
- Użyj zestawu Chat SDK dla języka C# (Azure.Communication.Chat) 1.3.0 lub najnowszej wersji. Aby uzyskać więcej informacji, zobacz Biblioteka klienta usługi Azure Communication Chat dla platformy .NET.
Goal
previewUri
Pobierz właściwość dla wbudowanych załączników obrazów.
Obsługa obrazów wbudowanych dla nowych komunikatów
W przewodniku Szybki start sondujesz komunikaty i dołączasz nowe komunikaty do messageList
właściwości . Ta funkcja zostanie utworzona później w celu uwzględnienia analizowania i pobierania obrazów wbudowanych.
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}");
}
}
Z przychodzącego zdarzenia typu ChatMessageReceivedEvent
właściwość o nazwie attachments
zawiera informacje o obrazie wbudowanym. Wystarczy renderować obrazy wbudowane w interfejsie użytkownika.
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 }
}
Poniższy kod JSON jest przykładem tego, jak ChatAttachment
może wyglądać załącznik obrazu:
"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"
}
]
Teraz wróć i zastąp kod, aby dodać dodatkową logikę do analizowania i pobierania załączników obrazów:
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}");
}
W tym przykładzie pobierasz wszystkie załączniki z wiadomości typu Image
, a następnie pobierasz każdy z obrazów. Musisz użyć elementu Token
w Bearer
części nagłówka żądania do celów autoryzacji. Po pobraniu obrazu można przypisać go do InlineImage
elementu widoku.
Możesz również dołączyć listę identyfikatorów URI załącznika, które mają być wyświetlane wraz z wiadomością na liście wiadomości SMS.
Demonstracja
- Uruchom aplikację ze zintegrowanego środowiska projektowego (IDE).
- Wprowadź link do spotkania usługi Teams.
- Dołącz do spotkania.
- Przyznaj użytkownika po stronie aplikacji Teams.
- Wyślij wiadomość ze strony aplikacji Teams przy użyciu obrazu.
Adres URL dołączony do wiadomości zostanie wyświetlony na liście wiadomości. Ostatni odebrany obraz jest renderowany w dolnej części okna.
Następne kroki
- Dowiedz się więcej o innych obsługiwanych funkcjach współdziałania.
- Zapoznaj się z naszym przykładem bohatera czatu.
- Dowiedz się więcej o sposobie działania czatu.