Udostępnij za pośrednictwem


Samouczek: włączanie obsługi załączników plików w aplikacji czatu

Zestaw SDK czatu bezproblemowo współpracuje z usługą Microsoft Teams w kontekście spotkania. Tylko użytkownik usługi Teams może wysyłać załączniki plików do użytkownika usług Azure Communication Services. Użytkownik usług Azure Communication Services nie może wysyłać załączników plików do użytkownika usługi Teams. Aby uzyskać informacje o bieżących możliwościach, zobacz Czat międzyoperaowy usługi Teams.

Obsługa dodawania załączników plików

Zestaw SDK czatu previewUrl udostępnia właściwość dla każdego załącznika pliku. W szczególności linki do strony internetowej w programie SharePoint, previewUrl gdzie użytkownik może wyświetlać zawartość pliku, edytować plik i pobierać plik, jeśli jest to możliwe.

Niektóre ograniczenia są skojarzone z tą funkcją:

  • Administrator usługi Teams dzierżawy nadawcy może narzucić zasady ograniczające lub całkowicie wyłączające tę funkcję. Na przykład administrator usługi Teams może wyłączyć pewne uprawnienia (takie jak Anyone), które mogą spowodować, że adres URL załącznika pliku (previewUrl) będzie niedostępny.

  • Obecnie obsługujemy tylko dwa uprawnienia do plików:

    • Anyone
    • People you choose (z adresem e-mail)

    Poinformuj użytkowników usługi Teams, że wszystkie inne uprawnienia (takie jak People in your organization) nie są obsługiwane. Użytkownicy usługi Teams powinni dokładnie sprawdzić, czy domyślne uprawnienie jest obsługiwane po przekazaniu pliku na klienta usługi Teams.

  • Adres URL pobierania bezpośredniego (url) nie jest obsługiwany.

Oprócz zwykłych fileplików (z AttachmentType ), zestaw SDK czatu AttachmentType udostępnia również właściwość image. Użytkownicy usług Azure Communication Services mogą dołączać obrazy w sposób dublujący zachowanie sposobu konwertowania załącznika obrazu przez klienta usługi Microsoft Teams na obrazy wbudowane w warstwie interfejsu użytkownika. Aby uzyskać więcej informacji, zobacz Handle image attachments (Obsługa załączników obrazów).

Użytkownicy usług Azure Communication Services mogą dodawać obrazy za pośrednictwem funkcji Przekazywania z tego urządzenia, co renderuje się po stronie usługi Teams, a zestaw SDK czatu zwraca takie załączniki jak image. W przypadku obrazów przekazywanych za pośrednictwem dołączania plików w chmurze obrazy są traktowane jako zwykłe pliki po stronie usługi Teams, dzięki czemu zestaw SDK czatu zwraca takie załączniki jak file.

Należy również pamiętać, że użytkownicy usług Azure Communication Services mogą przekazywać pliki tylko za pomocą przeciągania i upuszczania lub poleceń menu załączników Przekaż z tego urządzenia i Dołącz pliki w chmurze. Niektóre typy wiadomości z osadzonymi multimediami (takimi jak klipy wideo, wiadomości audio i karty pogodowe) nie są obecnie obsługiwane.

W tym samouczku opisano sposób włączania obsługi załączników plików przy użyciu zestawu SDK czatu usług Azure Communication Services dla języka JavaScript.

Przykładowy kod

Znajdź sfinalizowany kod tego samouczka w witrynie GitHub.

Wymagania wstępne

Cele

  • Renderuj załącznik pliku w wątku wiadomości. Każda karta załącznika pliku ma przycisk Otwórz .
  • Renderuj załączniki obrazów jako obrazy wbudowane.

Obsługa załączników plików

Zestaw Chat SDK dla języka JavaScript zwraca ChatAttachmentType właściwość file dla zwykłych załączników plików i image obrazów z obsługą komunikatów.

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";

Na przykład poniższy kod JSON pokazuje, jak ChatAttachment może wyglądać załącznik obrazu i załącznik pliku:

"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"
      }
]

Teraz wróćmy do procedury obsługi zdarzeń utworzonej w przewodniku Szybki start: dołącz aplikację Czat do spotkania usługi Teams i dodaj dodatkową logikę do obsługi załączników z właściwością attachmentTypefile:

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>';
}

Upewnij się, że dodano kod CSS dla karty załącznika:

  /* 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;
}

To wszystko, czego potrzebujesz do obsługi załączników plików. Następnie uruchomimy kod.

Uruchamianie kodu

W przypadku pakietu webpack możesz użyć webpack-dev-server właściwości , aby skompilować i uruchomić aplikację. 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

Lub:

npm start

Pokaz załącznika pliku

  1. Otwórz przeglądarkę i przejdź do http://localhost:8080/. Wprowadź adres URL spotkania i identyfikator wątku.

  2. Wyślij załączniki plików z klienta usługi Teams.

    Zrzut ekranu przedstawiający klienta usługi Teams z wysłanym komunikatem z trzema załącznikami plików.

  3. Powinien zostać wyświetlony nowy komunikat renderowany wraz z załącznikami plików.

    Zrzut ekranu przedstawiający przykładową aplikację z odebraną wiadomością przychodzącą z trzema załącznikami plików.

Obsługa załączników obrazów

Załączniki obrazów muszą być traktowane inaczej niż standardowe file załączniki. Załączniki obrazów mają attachmentType właściwość image, która wymaga tokenu komunikacyjnego w celu pobrania podglądu lub obrazów o pełnym rozmiarze.

Przed kontynuowaniem ukończ samouczek, który pokazuje, jak włączyć obsługę obrazów wbudowanych w aplikacji Czat. W tym samouczku opisano sposób pobierania obrazów, które wymagają tokenu komunikacyjnego w nagłówku żądania. Po otrzymaniu obiektu blob obrazu należy utworzyć właściwość wskazującą ObjectUrl ten obiekt blob. Następnie należy wstrzyknąć ten adres URL do src atrybutu każdego obrazu wbudowanego.

Teraz, gdy znasz sposób działania obrazów wbudowanych, możesz renderować załączniki obrazów, takie jak zwykły obraz wbudowany.

Najpierw należy wstrzyknąć image tag do zawartości wiadomości za każdym razem, gdy istnieje załącznik obrazu:

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">`
}

Teraz pożyczymy fetchPreviewImages() z samouczka : włącz obsługę obrazów wbudowanych i użyjmy jej bez żadnych zmian:

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');
    });
}

Ta funkcja wymaga właściwości, więc potrzebna jest globalna tokenString kopia zainicjowana w init()pliku , jak pokazano w poniższym fragmencie kodu:

var tokenString = '';

async function init() {
    ...
    const {
        token,
        expiresOn
    } = tokenResponse;
    
    tokenString = token;
    ...
}

Teraz masz obsługę załączników obrazów. Kontynuuj uruchamianie kodu i zobacz, jak działa.

Pokaz załącznika obrazu

  1. Wyślij załączniki obrazów z klienta usługi Teams.

    Zrzut ekranu przedstawiający klienta usługi Teams z wyświetlonym polem wysyłania z przekazanym załącznikiem obrazu.

  2. Po wysłaniu załącznika obrazu zwróć uwagę, że staje się on obrazem wbudowanym po stronie klienta usługi Teams.

    Zrzut ekranu przedstawiający klienta usługi Teams z komunikatem z załącznikiem obrazu wysłanym do drugiego uczestnika.

  3. Wróć do przykładowej aplikacji i upewnij się, że ten sam obraz jest renderowany.

    Zrzut ekranu przedstawiający przykładową aplikację z komunikatem przychodzącym z jednym obrazem wbudowanym renderowany.

W tym samouczku opisano sposób włączania obsługi załączników plików 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 załączników plików.
  • Obsługa załączników obrazów.

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 zgodnie z opisem w temacie 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.
  • Pobierz zestaw SDK czatu dla języka C# (@azure/communication-chat) 1.3.0 lub najnowszy. Aby uzyskać więcej informacji, zobacz Biblioteka klienta usługi Azure Communication Chat.

Przykładowy kod

Znajdź sfinalizowany kod dla tego samouczka w witrynie GitHub.

Obsługa załączników plików

Zestaw Chat SDK dla języka C# zwraca ChatAttachmentType właściwość file dla zwykłych załączników plików i image obrazów wbudowanych.

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);
}


Na przykład poniższy kod JSON pokazuje, jak ChatAttachment może wyglądać załącznik obrazu i załącznik pliku po otrzymaniu żądań po stronie serwera:

"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"
      }
]

Teraz wróć do procedury obsługi zdarzeń utworzonej w poprzednim przewodniku Szybki start i dodaj dodatkową logikę do obsługi załączników z właściwością fileChatAttachmentType :


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}");
    }
}

W szczególności dla każdego załącznika pliku uzyskasz previewUrl właściwość i skonstruujesz listę adresów URL w pliku for loop. Następnie osadzasz ciąg wraz z zawartością wiadomości czatu.

Obsługa załączników obrazów

Załączniki obrazów muszą być obsługiwane inaczej niż standardowe file załączniki. Załączniki obrazów mają ChatAttachmentType właściwość image, która wymaga tokenu komunikacyjnego w celu pobrania podglądu lub obrazów o pełnym rozmiarze.

Przed kontynuowaniem ukończ samouczek Włączanie obsługi obrazów wbudowanych. Aby uzyskać załączniki obrazów tożsamości, należy sprawdzić, czy zawartość wiadomości zawiera ten sam identyfikator obrazu z załączników.

bool isImageAttachment = message.Content.Message.Contains(x.Id);

Jeśli ta flaga ma wartość true, zastosuj logikę obrazu wbudowanego, aby ją renderować:

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);
}

Teraz aplikacja obsługuje załączniki obrazów.

Następne kroki