Oktatóanyag: Beágyazott kép támogatásának engedélyezése a csevegőalkalmazásban
A Csevegő SDK-t úgy tervezték, hogy zökkenőmentesen működjön együtt a Microsoft Teamsszel. A Csevegő SDK megoldást kínál beágyazott képek fogadására és beágyazott képek küldésére a Microsoft Teams felhasználóinak.
Ebben az oktatóanyagban megtudhatja, hogyan engedélyezheti a beágyazott rendszerképek támogatását az Azure Communication Services Chat SDK for JavaScript használatával.
A beágyazott képek olyan képek, amelyek közvetlenül a Teams-ügyfél küldési mezőjébe vannak másolva és beillesztve. Az eszköz menüjéből vagy húzással, például a Teams küldési mezőjébe közvetlenül áthúzott képek esetében a fájlmegosztási funkció részeként tekintse meg ezt az oktatóanyagot. (Lásd a "Képmellékletek kezelése" című szakaszt.)
A rendszerkép másolásához a Teams-felhasználók két lehetőséget választhatnak:
- Az operációs rendszer helyi menüjével másolja a képfájlt, majd illessze be a Teams-ügyfél küldési mezőjébe.
- Billentyűparancsok használata.
Ebben az oktatóanyagban megtudhatja, mit kell tennie, ha:
Feljegyzés
A beágyazott képek küldésének lehetősége jelenleg nyilvános előzetes verzióban érhető el. Csak JavaScripthez érhető el. Beágyazott képek fogadásához jelenleg általánosan elérhető. JavaScript és C# nyelven is elérhető egy Teams együttműködési csevegésben.
Előfeltételek
- Tekintse át a Csevegőalkalmazás csatlakoztatása Teams-értekezlethez című rövid útmutatót.
- Hozzon létre egy Azure Communication Services-erőforrást. További információ: Azure Communication Services-erőforrás létrehozása. Ehhez az oktatóanyaghoz rögzítenie kell a kapcsolati sztring.
- Állítson be egy Teams-értekezletet az üzleti fiókjával, és készítse elő az értekezlet URL-címét.
- Használja a Chat SDK for JavaScript (@azure/communication-chat) 1.4.0-s vagy legújabb verziójának használatát. További információ: Azure Communication Chat ügyféloldali kódtár JavaScripthez.
Mintakód
Keresse meg az oktatóanyag véglegesített kódját a GitHubon.
Fogadott beágyazott képek kezelése új üzeneteseményben
Ebben a szakaszban megtudhatja, hogyan jeleníthet meg beágyazott képeket egy új fogadott esemény üzenettartalmaiba ágyazva.
A rövid útmutatóban létrehozott egy eseménykezelőt az chatMessageReceived
eseményhez, amely akkor aktiválódik, amikor új üzenetet kap a Teams-felhasználótól. A bejövő üzenet tartalmát messageContainer
is hozzáfűzi közvetlenül az chatMessageReceived
esemény fogadása után a chatClient
következőhöz:
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;
}
A bejövő típusú ChatMessageReceivedEvent
eseményből egy elnevezett attachments
tulajdonság információkat tartalmaz a beágyazott rendszerképről. Mindössze ennyi kell ahhoz, hogy beágyazott képeket jelenítsen meg a felhasználói felületen:
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";
Most térjen vissza az előző kódhoz, és adjon hozzá néhány további logikát, például a következő kódrészleteket:
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;
});
}
Ebben a példában két segédfüggvényt setImgHandler
és egy segédfüggvényt hozott létre. fetchPreviewImages
Az első az előnézeti képet közvetlenül az previewURL
egyes ChatAttachment
objektumokban lévő, hitelesítési fejléccel ellátott objektumokból olvassa be. Hasonlóképpen beállít egy eseményt onclick
a függvény setImgHandler
minden képéhez. Az eseménykezelőben egy teljes méretű képet fog lekérni a tulajdonságból url
egy ChatAttachment
hitelesítési fejléccel rendelkező objektumból.
Most közzé kell tennie a jogkivonatot a globális szinten, mert egy hitelesítési fejlécet kell létrehoznia vele. Módosítania kell a következő kódot:
// 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;
...
}
Ha egy átfedésben szeretné megjeleníteni a teljes méretű képet, új összetevőt is hozzá kell adnia:
<div class="overlay" id="overlay-container">
<div class="content">
<img id="full-scale-image" src="" alt="" />
</div>
</div>
Néhány CSS-sel:
/* 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
}
Most, hogy be van állítva egy átfedés, itt az ideje, hogy dolgozzon a logikán a teljes méretű képek rendereléséhez. Ne feledje, hogy egy függvény fetchFullScaleImage
meghívásához létrehozott egy onClick
eseménykezelőt:
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';
}
Az egyik utolsó dolog, amit hozzá szeretne adni, az a lehetőség, hogy a kép kattintásakor el tudja utasítani az átfedést:
loadingImageOverlay.addEventListener('click', () => {
overlayContainer.style.display = 'none';
});
Most végrehajtotta a valós idejű értesítésekből érkező üzenetek beágyazott rendszerképeinek megjelenítéséhez szükséges összes módosítást.
A kód futtatása
A Webpack-felhasználók létrehozhatják webpack-dev-server
és futtathatják az alkalmazást. Futtassa az alábbi parancsot az alkalmazás gazdagépének helyi webkiszolgálón való kötegeléséhez:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Bemutató
Nyissa meg a böngészőt, és nyissa meg a kívánt elemet http://localhost:8080/
. Adja meg az értekezlet URL-címét és a szálazonosítót. Küldjön néhány beágyazott képet a Teams-ügyfélről.
Ezután az új üzenetnek az előnézeti képekkel együtt kell megjelennie.
Miután az Azure Communication Services felhasználója kiválasztotta az előnézeti képet, megjelenik egy átfedés a Teams-felhasználó által küldött teljes méretű képpel.
Beágyazott képek küldésének kezelése új üzenetkérelemben
Fontos
Az Azure Communication Services ezen funkciója jelenleg előzetes verzióban érhető el.
Az előzetes verziójú API-k és SDK-k szolgáltatásszintű szerződés nélkül érhetők el. Javasoljuk, hogy éles számítási feladatokhoz ne használja őket. Előfordulhat, hogy egyes funkciók nem támogatottak, vagy korlátozott képességekkel rendelkeznek.
További információkért tekintse át a Microsoft Azure Előzetes verzió kiegészítő használati feltételeit.
A Beágyazott képekkel ellátott üzenetek kezelése mellett a JavaScripthez készült Csevegő SDK is kínál megoldást arra, hogy a kommunikációs felhasználó beágyazott képeket küldjön a Microsoft Teams-felhasználónak egy együttműködési csevegésben.
Tekintse meg az új API-t a következőből ChatThreadClient
:
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
"onUploadProgress": reportProgressCallback
});
Az API egy képblobot, egy fájlnév-sztringet és egy függvényvisszahívást vesz fel, amely a feltöltés előrehaladását jelenti.
Ha képet szeretne küldeni más csevegő résztvevőnek, a következőkre van szüksége:
- Töltse fel a képet az
uploadImage
API-valChatThreadClient
, és mentse a visszaadott objektumot. - Írja meg az üzenet tartalmát, és állítson be egy mellékletet az előző lépésben mentett visszaadott objektumhoz.
- Küldje el az új üzenetet az
sendMessage
API-bólChatThreadClient
.
Hozzon létre egy új fájlválasztót, amely elfogadja a képeket:
<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>
Most állítson be egy eseményfigyelőt arra az esetre, ha állapotváltozás történik:
document.getElementById("upload").addEventListener("change", uploadImages);
Új függvényt kell létrehoznia az állapotváltozások esetén:
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);
}
Ebben a példában létrehozott egy-egy FileReader
képet az egyes képek kódolt képként base64
való olvasásához, majd a ChatSDK API meghívása előtt létrehozott egy Blob
fájlt a feltöltésükhöz. Létrehozott egy globálist uploadedImageModels
a feltöltött képek adatmodelljeinek mentéséhez a Csevegő SDK-ból.
Végül módosítania kell a sendMessageButton
korábban létrehozott eseményfigyelőt a feltöltött képek csatolásához.
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}`);
});
Ennyi az egész. Most futtassa a kódot, hogy működés közben láthassa.
A kód futtatása
A Webpack-felhasználók létrehozhatják webpack-dev-server
és futtathatják az alkalmazást. Futtassa az alábbi parancsot az alkalmazás gazdagépének helyi webkiszolgálón való kötegeléséhez:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Bemutató
Nyissa meg a böngészőt, és nyissa meg a kívánt elemet http://localhost:8080/
. A küldési mezőben egy új szakasz található a képek csatolásához.
Ezután kiválaszthatja a csatolni kívánt képeket.
A Teams-felhasználónak most meg kell kapnia az imént elküldött képet, amikor a Küldés lehetőséget választja.
Ez az oktatóanyag bemutatja, hogyan engedélyezheti a beágyazott rendszerképek támogatását az Azure Communication Services Chat SDK for C# használatával.
Ebben az oktatóanyagban az alábbiakkal fog megismerkedni:
- Új üzenetek beágyazott lemezképeinek kezelése.
Előfeltételek
- Tekintse át a Csevegőalkalmazás csatlakoztatása Teams-értekezlethez című rövid útmutatót.
- Hozzon létre egy Azure Communication Services-erőforrást. További információ: Azure Communication Services-erőforrás létrehozása. Ehhez az oktatóanyaghoz rögzítenie kell a kapcsolati sztring.
- Állítson be egy Teams-értekezletet az üzleti fiókjával, és készítse elő az értekezlet URL-címét.
- Használja a Chat SDK for C# (Azure.Communication.Chat) 1.3.0-s vagy legújabb verziójának használatát. További információ: Azure Communication Chat ügyféloldali kódtár a .NET-hez.
Cél
previewUri
A beágyazott képmellékletek tulajdonságának megragadása.
Új üzenetek beágyazott lemezképeinek kezelése
A rövid útmutatóban lekérdezi az üzeneteket, és hozzáfűzi az új üzeneteket a messageList
tulajdonsághoz. Erre a funkcióra később építhet, így elemezheti és lekérheti a beágyazott képeket.
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}");
}
}
A bejövő típusú ChatMessageReceivedEvent
eseményből a névvel ellátott attachments
tulajdonság információkat tartalmaz a beágyazott rendszerképről. Mindössze ennyi kell ahhoz, hogy beágyazott képeket jelenítsen meg a felhasználói felületen.
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 }
}
Az alábbi JSON egy példa ChatAttachment
egy képmellékletre:
"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"
}
]
Most lépjen vissza, és cserélje le a kódot, hogy további logikát adjon hozzá a képmellékletek elemzéséhez és lekéréséhez:
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}");
}
Ebben a példában a típusüzenet Image
összes mellékletét megragadja, majd beolvassa az egyes képeket. Engedélyezési célokra a Bearer
kérelem fejlécének a részében kell használniaToken
. A kép letöltése után hozzárendelheti a InlineImage
nézet eleméhez.
A melléklet URI-jainak listáját is tartalmaznia kell a szöveges üzenetlistában megjelenő üzenettel együtt.
Bemutató
- Futtassa az alkalmazást az integrált fejlesztési környezetből (IDE).
- Adja meg a Teams-értekezlet hivatkozását.
- Csatlakozzon az értekezlethez.
- Fogadja el a felhasználót a Teams oldalán.
- Küldjön egy üzenetet a Teams oldaláról egy képpel.
Az üzenethez tartozó URL-cím megjelenik az üzenetlistában. Az utolsó fogadott kép az ablak alján jelenik meg.
Következő lépések
- További információ az egyéb támogatott együttműködési funkciókról.
- Tekintse meg a csevegési főhősünk mintáját.
- További információ a csevegés működéséről.
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: