Envío y recepción de archivos

Los agentes pueden recibir, leer y enviar documentos en conversaciones de Microsoft Teams. Teams almacena estos archivos en OneDrive o SharePoint y los muestra como tarjetas de archivo o elementos almacenados.

Use el SDK de Teams para recibir archivos en chats personales y enviar archivos a través del consentimiento de archivos del bot. Use Microsoft Graph cuando el agente deba trabajar con archivos almacenados en chats personales, chats grupales y canales. Para las imágenes que se representan directamente en una conversación, consulte Enviar y recibir imágenes en línea.

Importante

Los agentes no admiten flujos de trabajo de envío y recepción de archivos de documentos en Government Community Cloud High (GCC High), Departamento de Defensa (DoD) o Teams operados por 21Vianet.

Experiencia del usuario

Comprenda cómo los usuarios intercambian documentos con un agente para que pueda proporcionar indicaciones claras, solicitudes de consentimiento y confirmaciones. Los usuarios pueden:

  • Adjunte un documento a un chat personal con un agente.
  • Revisar y aceptar o rechazar un archivo ofrecido por un agente.
  • Abra un archivo cargado correctamente desde su tarjeta de archivo.
  • Trabaje con archivos almacenados de OneDrive o SharePoint en todos los ámbitos de conversación compatibles.

Un documento recibido se almacena en OneDrive o SharePoint y aparece como una tarjeta de archivo o un elemento almacenado. Un bot que envía un archivo en un chat personal primero pide consentimiento, carga el archivo después de la aceptación y, a continuación, envía una tarjeta de información de archivo.

Experiencia del desarrollador

Elija una API de archivo en función de la identidad de la aplicación, la dirección y el ámbito de conversación. Las siguientes opciones coinciden con el orden de implementación de este artículo:

Requisito Enfoque recomendado
Recibir y leer un documento en un chat personal Descriptor de acceso de archivos del SDK de Teams
Enviar o recuperar archivos almacenados entre los ámbitos de conversación Microsoft Graph
Enviar un documento desde un bot en un chat personal Consentimiento de archivos del SDK de Teams

El descriptor de acceso de archivo del SDK de Teams filtra la colección de datos adjuntos de actividades y expone los documentos admitidos como identificadores de archivo entrante diferidos. Los usuarios de Agentic recuperan bytes de archivos a través de Microsoft Graph con su identidad. Los bots tradicionales usan la dirección URL preautorizada y de corta duración proporcionada por Teams.

Operación Chat personal Chat de grupo Canal Requisito
Recibir archivos con el descriptor de acceso de archivos del SDK de Teams Compatible No se admite explícitamente No se admite explícitamente Los usuarios de Agentic requieren permisos de archivo de Graph. Los bots usan una dirección URL previamente autorizada.
Enviar o recuperar archivos con Graph Compatible Compatible Compatible Configure los permisos para la ubicación de almacenamiento, la API, la identidad de llamada y el modelo de acceso.
Enviar archivos con consentimiento de archivos de bots Compatible No se admite No se admite Establézcalo supportsFiles en true en la entrada del bot.

Recibir archivos

Recibe archivos de documentos que los usuarios adjuntan a chats personales para que tu agente pueda inspeccionar o procesar su contenido. Configure primero el acceso a los archivos y luego use el descriptor de acceso de archivos del SDK de Teams para enumerar y leer cada archivo recibido.

Configurar la compatibilidad con archivos

Configure la compatibilidad con archivos para que el agente o bot tenga los permisos y la configuración de plataforma necesarios para recibir documentos. Complete la configuración de la identidad de la aplicación antes de implementar controladores de archivos.

La configuración necesaria depende de la identidad y la operación del archivo:

Escenario Actualización del manifiesto de la aplicación Otra configuración
El usuario agente recibe un archivo Ninguno Agregue un permiso de archivo de Microsoft Graph al plano técnico del agente y obtenga el consentimiento del administrador.
El bot recibe o envía un archivo a través del consentimiento de archivo Establézcalo supportsFiles en true en la entrada del bot. Ninguno para la dirección URL del archivo preautorizado proporcionado por Teams.
La aplicación envía o recupera un archivo almacenado con Microsoft Graph Ninguna propiedad de manifiesto de aplicación específica de archivo Configure los permisos y la autenticación de Microsoft Graph necesarios para la identidad de llamada.

Usuario agente

Para un usuario agente, no es necesario establecer supportsFiles ni agregar otra propiedad de manifiesto de aplicación específica de archivo. Configure un permiso de archivo de Microsoft Graph en el plano técnico del agente y obtenga el consentimiento del administrador. El usuario agente recupera el contenido del archivo a través de Microsoft Graph con su propia identidad. Para obtener más información, vea permisos heredables.

Importante

Configure y acepte el permiso del plano técnico antes de probar la recuperación de archivos. Sin una credencial de Graph, el SDK genera un error de credenciales de archivo.

Bot

Para un bot que recibe archivos o usa el consentimiento de archivos, establézcalo supportsFilestrue en la entrada del bot del manifiesto de la aplicación:

{
  "bots": [
    {
      "botId": "${{BOT_ID}}",
      "scopes": ["personal"],
      "supportsFiles": true
    }
  ]
}

Valores clave:

  • botId: se establece ${{BOT_ID}} para identificar el registro de bots.
  • scopes: agregue personal para habilitar las interacciones de archivos uno a uno.
  • supportsFiles: establézcalo true para exponer el control de datos adjuntos de archivo.

Sin supportsFiles: true, los usuarios no pueden adjuntar archivos en un chat personal con el bot y el descriptor de acceso de archivo devuelve una colección vacía. Esta configuración no concede permisos de Microsoft Graph.

Acceso a los archivos y metadatos recibidos

Cuando un usuario adjunta un documento en un chat personal, Teams lo almacena en OneDrive o SharePoint. La actividad de mensajes contiene metadatos de archivos y el descriptor de acceso de archivos del SDK de Teams proporciona acceso diferido a los bytes de archivos.

Se usa ListAsync() para tener acceso a todos los archivos compatibles adjuntos al mensaje actual:

teamsApp.OnMessage(async (context, cancellationToken) =>
{
    IList<IncomingFile> files =
        await context.Files.ListAsync(cancellationToken);

    if (files.Count == 0)
    {
        await context.ReplyAsync(
            "Attach a file and I will read it.",
            cancellationToken);
        return;
    }

    string names = string.Join(", ", files.Select(file => file.Name));
    await context.ReplyAsync(
        $"You sent {files.Count} file(s): {names}",
        cancellationToken);
});

API y valores clave:

  • context.Files.ListAsync: devuelve metadatos de archivo sin descargar bytes de archivo.
  • file.Name: lee el nombre proporcionado por el cargador para solo mostrar.

ListAsync() Conserva el orden de los datos adjuntos. Devuelve una colección vacía para las actividades sin archivos compatibles y omite las entradas de archivo con formato incorrecto. Úselo FirstAsync() cuando su controlador espera un archivo:

IncomingFile? file =
    await context.Files.FirstAsync(cancellationToken);

if (file is not null)
{
    await context.ReplyAsync(
        $"Reading {file.Name}...",
        cancellationToken);
}

API y valores clave:

  • FirstAsync: devuelve el primer archivo admitido o null.
  • file.Name: muestra el nombre proporcionado por el cargador del archivo recibido.

Se usa list() para tener acceso a todos los archivos compatibles adjuntos al mensaje actual:

app.on('message', async ({ files, send }) => {
  const attached = await files.list();

  if (attached.length === 0) {
    await send('Attach a file and I will read it.');
    return;
  }

  const names = attached.map((file) => file.name).join(', ');
  await send(`You sent ${attached.length} file(s): ${names}`);
});

API y valores clave:

  • files.list: devuelve metadatos de archivo sin descargar bytes de archivo.
  • file.name: lee el nombre proporcionado por el cargador para solo mostrar.

list() Conserva el orden de los datos adjuntos. Devuelve una matriz vacía para las actividades sin archivos compatibles y omite las entradas de archivo con formato incorrecto. Úselo first() cuando su controlador espera un archivo:

const file = await files.first();

if (file) {
  await send(`Reading ${file.name}...`);
}

API y valores clave:

  • first: devuelve el primer archivo admitido o undefined.
  • file.name: muestra el nombre proporcionado por el cargador del archivo recibido.

Se usa list() para tener acceso a todos los archivos compatibles adjuntos al mensaje actual:

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]) -> None:
    attached = await ctx.files.list()

    if not attached:
        await ctx.reply("Attach a file and I will read it.")
        return

    names = ", ".join(file.name for file in attached)
    await ctx.reply(f"You sent {len(attached)} file(s): {names}")

API y valores clave:

  • ctx.files.list: devuelve metadatos de archivo sin descargar bytes de archivo.
  • file.name: lee el nombre proporcionado por el cargador para solo mostrar.

list() Conserva el orden de los datos adjuntos. Devuelve una lista vacía para las actividades sin archivos compatibles y omite las entradas de archivo con formato incorrecto. Úselo first() cuando su controlador espera un archivo:

file = await ctx.files.first()

if file:
    await ctx.reply(f"Reading {file.name}...")

API y valores clave:

  • first: devuelve el primer archivo admitido o None.
  • file.name: muestra el nombre proporcionado por el cargador del archivo recibido.

Un identificador de archivo entrante incluye:

  • Id. único: Id. de elemento de unidad de OneDrive o SharePoint cuando esté disponible.
  • Nombre: nombre de archivo proporcionado por el cargador, incluida su extensión de archivo.
  • Extensión: extensión proporcionada por la plataforma sin el punto inicial.
  • Tipo de contenido: tipo MIME cuando lo proporciona el origen.
  • Ámbito: ámbito de la conversación en el que se recibió el archivo.
  • Origen: SDK origen que identificó el archivo entrante.
  • Dirección URL de contenido: Dirección URL de almacenamiento navegable, no necesariamente una dirección URL de descarga.
  • Datos adjuntos sin formato: metadatos originales para diagnósticos de nivel de protocolo.

Precaución

Trátelo Name como una entrada que no es de confianza. Antes de escribir un archivo, reemplácelo por un nombre seguro generado por la aplicación o desinfecte y verifique que el destino resuelto permanezca dentro de un directorio controlado por la aplicación.

Leer un archivo recibido

Lee un archivo recibido cuando la aplicación necesite su texto o contenido binario para su procesamiento, almacenamiento o análisis. Use el método de descarga para una copia reutilizable en memoria o seleccione un método de streaming para archivos grandes.

Se usa DownloadAsync() para descargar un archivo en una copia reutilizable en memoria:

IncomingFile? file =
    await context.Files.FirstAsync(cancellationToken);

if (file is not null)
{
    DownloadedFile downloaded =
        await file.DownloadAsync(cancellationToken);

    await context.ReplyAsync(
        $"Downloaded {downloaded.Filename} " +
        $"({downloaded.Bytes.Length} bytes, {downloaded.ContentType}).",
        cancellationToken);
}

API y valores clave:

  • DownloadAsync: Capturar y almacenar en búfer una copia reutilizable de bytes.
  • downloaded.Bytes: acceda al contenido binario completo del archivo descargado.
  • downloaded.ContentType: use el tipo MIME resuelto para el procesamiento.
  • downloaded.Filename: usa el nombre resuelto para mostrar el nombre.

Otras opciones de lectura incluyen:

  • TextAsync(): descarga y descodifica texto como UTF-8 de forma predeterminada.
  • StreamAsync(): procese archivos grandes sin almacenarlos en búfer por completo.
  • SaveAsAsync(path): haga Stream bytes directamente a una ruta de acceso local segura.

TextAsync() Reemplaza las secuencias de bytes no válidas por U+FFFD. Proporcione un Encoding texto no UTF-8 y procese archivos binarios como bytes o secuencias.

An IncomingFile no almacena bytes en memoria caché. Cada llamada a DownloadAsync(), TextAsync(), StreamAsync(), o SaveAsAsync() realiza otra solicitud de red. Descárgalo una vez y vuelve a usarlo DownloadedFile cuando necesites el mismo contenido más de una vez:

DownloadedFile downloaded =
    await file.DownloadAsync(cancellationToken);

string text = downloaded.Text();
byte[] bytes = downloaded.Bytes;

await downloaded.SaveAsAsync(
    "./downloads/copy.bin",
    cancellationToken);

API y valores clave:

  • downloaded.Text(): descodifica la copia almacenada en búfer sin otra descarga.
  • downloaded.Bytes: reutilizar los bytes almacenados en búfer para el procesamiento binario.
  • SaveAsAsync: guarde los bytes almacenados en búfer sin recuperar el archivo de nuevo.

Se usa download() para descargar un archivo en una copia reutilizable en memoria:

const file = await files.first();

if (file) {
  const downloaded = await file.download();
  await send(
    `Downloaded ${downloaded.filename} ` +
    `(${downloaded.bytes.length} bytes, ${downloaded.contentType}).`
  );
}

API y valores clave:

  • download: Capturar y almacenar en búfer una copia reutilizable de bytes.
  • downloaded.bytes: acceda al contenido binario del archivo descargado.
  • downloaded.contentType: use el tipo MIME resuelto para el procesamiento.
  • downloaded.filename: usa el nombre resuelto para mostrar el nombre.

Otras opciones de lectura incluyen:

  • text(): descarga y descodifica texto como UTF-8 de forma predeterminada.
  • stream(): procese archivos grandes sin almacenarlos en búfer por completo.
  • saveAs(path): haga Stream bytes directamente a una ruta de acceso local segura.

Un archivo entrante no almacena bytes en la memoria caché. Descarga una vez y vuelve a usar el archivo descargado cuando necesites el mismo contenido más de una vez:

const downloaded = await file.download();
const text = downloaded.text();
const buffer = downloaded.arrayBuffer();

await downloaded.saveAs('./downloads/copy.bin');

API y valores clave:

  • downloaded.text(): descodifica la copia almacenada en búfer sin otra descarga.
  • downloaded.arrayBuffer(): reutilizar los bytes almacenados en búfer para el procesamiento binario.
  • saveAs: guarde los bytes almacenados en búfer sin recuperar el archivo de nuevo.

Se usa download() para descargar un archivo en una copia reutilizable en memoria:

file = await ctx.files.first()

if file:
    downloaded = await file.download()
    await ctx.reply(
        f"Downloaded {downloaded.filename} "
        f"({len(downloaded.bytes)} bytes, {downloaded.content_type})."
    )

API y valores clave:

  • download: Capturar y almacenar en búfer una copia reutilizable de bytes.
  • downloaded.bytes: acceda al contenido binario del archivo descargado.
  • downloaded.content_type: use el tipo MIME resuelto para el procesamiento.
  • downloaded.filename: usa el nombre resuelto para mostrar el nombre.

Otras opciones de lectura incluyen:

  • text(): descarga y descodifica texto como UTF-8 de forma predeterminada.
  • stream(): procese archivos grandes sin almacenarlos en búfer por completo.
  • save_as(path): haga Stream bytes directamente a una ruta de acceso local segura.

Un archivo entrante no almacena bytes en la memoria caché. Descarga una vez y vuelve a usar el archivo descargado cuando necesites el mismo contenido más de una vez:

downloaded = await file.download()
text = downloaded.text()
data = downloaded.bytes

await downloaded.save_as("./downloads/copy.bin")

API y valores clave:

  • downloaded.text(): descodifica la copia almacenada en búfer sin otra descarga.
  • downloaded.bytes: reutilizar los bytes almacenados en búfer para el procesamiento binario.
  • save_as: guarde los bytes almacenados en búfer sin recuperar el archivo de nuevo.

Para un usuario agente, el SDK de Teams usa los datos adjuntos ContentUrl y la identidad del usuario agente para recuperar el archivo a través de Microsoft Graph. Para un bot, el SDK usa el programa de corta duración y previamente autorizado downloadUrl suministrado en la actividad. Las API de lectura de archivos que se muestran en esta sección se aplican a ambas rutas.

Obtener acceso a los datos adjuntos del archivo sin formato

Acceda a los datos adjuntos sin formato cuando necesite metadatos de protocolo que el descriptor de acceso del archivo con tipo no expone, por ejemplo, para diagnósticos o solución de problemas. Inspeccione la carga sin procesar solo cuando sea necesario y registre solo los campos no confidenciales seleccionados explícitamente.

Úselo IncomingFile.Raw solo cuando necesite la carga útil del protocolo original. En el ejemplo siguiente se registran el nombre de los datos adjuntos y el tipo de contenido, en lugar de serializar el objeto completo:

IncomingFile? file =
    await context.Files.FirstAsync(cancellationToken);

if (file is not null)
{
    logger.LogDebug(
        "File attachment received. Name: {Name}; Content type: {ContentType}",
        file.Raw.Name,
        file.Raw.ContentType);
}

API y valores clave:

  • file.Raw: accede a los metadatos originales para diagnóstico o solución de problemas.
  • file.Raw.Name: registre el nombre para mostrar sólo después de validar su confidencialidad.
  • file.Raw.ContentType: registra el tipo de datos adjuntos sin exponer sus direcciones URL.
  • logger.LogDebug: registra los metadatos seleccionados en lugar de la carga completa.

Úselo IIncomingFile.raw solo cuando necesite la carga útil del protocolo original. En el ejemplo siguiente se registran el nombre de los datos adjuntos y el tipo de contenido, en lugar del objeto completo:

const file = await files.first();

if (file) {
  log.debug('File attachment received', {
    name: file.raw.name,
    contentType: file.raw.contentType
  });
}

API y valores clave:

  • file.raw: accede a los metadatos originales para diagnóstico o solución de problemas.
  • file.raw.name: registre el nombre para mostrar sólo después de validar su confidencialidad.
  • file.raw.contentType: registra el tipo de datos adjuntos sin exponer sus direcciones URL.
  • log.debug: registra los metadatos seleccionados en lugar de la carga completa.

Úselo IncomingFile.raw solo cuando necesite la carga útil del protocolo original. En el ejemplo siguiente se registran el nombre de los datos adjuntos y el tipo de contenido, en lugar del objeto completo:

file = await ctx.files.first()

if file:
    ctx.logger.debug(
        "File attachment received. Name: %s; Content type: %s",
        file.raw.name,
        file.raw.content_type,
    )

API y valores clave:

  • file.raw: accede a los metadatos originales para diagnóstico o solución de problemas.
  • file.raw.name: registre el nombre para mostrar sólo después de validar su confidencialidad.
  • file.raw.content_type: registra el tipo de datos adjuntos sin exponer sus direcciones URL.
  • ctx.logger.debug: registra los metadatos seleccionados en lugar de la carga completa.

No registre URL de datos adjuntos sin procesar, identificadores o la carga completa. El descriptor de acceso al archivo no devuelve imágenes insertadas, tarjetas, menciones, vistas previas de vínculos, datos adjuntos HTML ni entradas de archivo con formato incorrecto. Acceda a estos elementos a través de la colección de datos adjuntos de la actividad. Para obtener instrucciones específicas de imágenes, consulte Enviar y recibir imágenes en línea.

Enviar archivos

Enviar documentos almacenados a los usuarios cuando la aplicación deba entregar informes generados, exportaciones u otro contenido descargable. Use Microsoft Graph para escenarios agenciales y de ámbito cruzado, o use el consentimiento de archivos de bots en chats personales.

Usar Microsoft Graph para los archivos almacenados

Use Microsoft Graph cuando la aplicación deba enviar o recuperar archivos almacenados en chats personales, chats grupales o canales:

  • Usar el OneDrive de un usuario para archivos de chat personal y grupal.
  • Use el sitio de SharePoint del equipo para los archivos de canal.
  • Obtenga el acceso de almacenamiento necesario a través de OAuth 2.0.
  • Publicar un mensaje adjunto que haga referencia a un archivo almacenado existente.

Para obtener más información, vea Enviar datos adjuntos de archivos de mensajes de chat y API de OneDrive y SharePoint.

Use el flujo de trabajo de consentimiento de archivos del bot para solicitar permiso antes de que el bot cargue un documento en OneDrive de un usuario. Implemente la siguiente secuencia para los chats personales:

  1. Enviar un FileConsentCard.
  2. Recibir una fileConsent/invoke actividad.
  3. Si el usuario acepta, cargue los bytes uploadUrl con HTTP PUT.
  4. Enviar un FileInfoCard vínculo al archivo cargado.
  5. Si el usuario lo rechaza, descarte el contenido pendiente.

Solicite consentimiento para que el usuario pueda revisar el nombre, el propósito y el tamaño de archivo antes de que la aplicación lo cargue en OneDrive. Enviar un FileConsentCard y conservar el contenido del archivo pendiente hasta que el usuario lo acepte o lo rechace.

En el mensaje siguiente se solicita permiso para cargar un archivo:

Tarjeta de consentimiento en la que se solicita permiso para cargar un archivo.

En dispositivos móviles, la solicitud de consentimiento aparece de la siguiente manera:

Tarjeta de consentimiento solicitando permiso para cargar un archivo en el móvil.
{
  "attachments": [
    {
      "contentType": "application/vnd.microsoft.teams.card.file.consent",
      "name": "file_example.txt",
      "content": {
        "description": "This is your monthly expense report.",
        "sizeInBytes": 1029393,
        "acceptContext": {
          "fileId": "expense-report-2026-09"
        },
        "declineContext": {
          "fileId": "expense-report-2026-09"
        }
      }
    }
  ]
}

Propiedades y valores clave:

  • contentType: usa el tipo de contenido de tarjeta de consentimiento de archivos que se muestra.
  • name: establezca el nombre de archivo que Teams muestra a los usuarios.
  • description: agrega un breve propósito para el archivo ofrecido.
  • sizeInBytes: establezca el tamaño exacto del archivo en bytes.
  • acceptContext: agrega los identificadores necesarios después de que el usuario acepte.
  • declineContext: agrega los identificadores necesarios después de que el usuario lo rechace.

Mantener los bytes de archivo pendientes fuera del objeto de contexto. Aplica directivas de expiración y limpieza a las cargas pendientes.

Gestionar aceptación o rechazo

Controla la respuesta de consentimiento para decidir si quieres cargar el archivo pendiente o descartarlo. Inspeccione la fileConsent/invoke acción y conserve solo los identificadores necesarios para localizar el contenido pendiente.

Cuando el usuario acepta, Teams envía fileConsent/invoke con action un valor establecido y accept un uploadInfo.uploadUrlarchivo . Si el usuario lo rechaza, action es decline.

Cargar contenido de archivo

Cargue los bytes pendientes solo después de que el usuario acepte el archivo. Use la dirección URL de carga proporcionada, los encabezados de intervalo de bytes necesarios y HTTP PUT, a continuación, compruebe que OneDrive devuelve un estado correcto.

Use la dirección URL de carga para transferir los bytes de archivo:

using System.Net;
using System.Net.Http.Headers;

async Task UploadToOneDrive(
    string url,
    byte[] content,
    CancellationToken cancellationToken)
{
    if (content.Length == 0)
    {
        throw new ArgumentException(
            "The file content must not be empty.",
            nameof(content));
    }

    using var request = new HttpRequestMessage(HttpMethod.Put, url);
    request.Content = new ByteArrayContent(content);
    request.Content.Headers.ContentType =
        new MediaTypeHeaderValue("application/octet-stream");
    request.Content.Headers.ContentLength = content.Length;
    request.Content.Headers.ContentRange =
        new ContentRangeHeaderValue(0, content.Length - 1, content.Length);

    using HttpResponseMessage response =
        await httpClient.SendAsync(request, cancellationToken);

    if (response.StatusCode is not HttpStatusCode.OK
        and not HttpStatusCode.Created)
    {
        throw new HttpRequestException(
            $"Upload failed with status {response.StatusCode}.");
    }
}

Parámetros y valores clave:

  • url: usar el devuelto después de la UploadInfo.UploadUrl aceptación.
  • content: proporciona los bytes exactos asociados al consentimiento.
  • content.Length: rechaza una carga vacía antes de crear su intervalo de bytes.
  • ContentType: Configurado application/octet-stream para la transferencia binaria.
  • ContentLength: establece el número exacto de bytes cargados.
  • ContentRange: describe el intervalo de bytes cargado y el total.
  • httpClient.SendAsync: envía la solicitud HTTP PUT a OneDrive.
  • response.StatusCode: acepta HTTP 200 o 201 y en caso contrario, fracasar.
import axios from 'axios';

async function uploadToOneDrive(url: string, content: Buffer): Promise<void> {
  if (content.length === 0) {
    throw new Error('The file content must not be empty.');
  }

  const fileSize = content.length;
  const response = await axios.put(url, content, {
    headers: {
      'Content-Type': 'application/octet-stream',
      'Content-Length': fileSize.toString(),
      'Content-Range': `bytes 0-${fileSize - 1}/${fileSize}`
    }
  });

  if (![200, 201].includes(response.status)) {
    throw new Error(`Upload failed with status ${response.status}`);
  }
}

Parámetros y valores clave:

  • url: usar el devuelto después de la uploadInfo.uploadUrl aceptación.
  • content: proporciona los bytes exactos asociados al consentimiento.
  • content.length: rechaza una carga vacía antes de crear su intervalo de bytes.
  • Content-Type: Configurado application/octet-stream para la transferencia de archivos binarios.
  • Content-Length: establece la longitud decimal de los bytes cargados.
  • Content-Range: describe el intervalo de bytes cargado y el total.
  • axios.put: cargue los bytes con una solicitud HTTP PUT .
  • response.status: acepta HTTP 200 o 201 y falla en otras respuestas.
import httpx

async def upload_to_onedrive(url: str, content: bytes) -> None:
    if not content:
        raise ValueError("The file content must not be empty.")

    file_size = len(content)
    headers = {
        "Content-Type": "application/octet-stream",
        "Content-Length": str(file_size),
        "Content-Range": f"bytes 0-{file_size - 1}/{file_size}",
    }

    async with httpx.AsyncClient() as client:
        response = await client.put(url, content=content, headers=headers)

    if response.status_code not in (200, 201):
        raise RuntimeError(
            f"Upload failed with status {response.status_code}"
        )

Parámetros y valores clave:

  • url: usar el devuelto después de la upload_info.upload_url aceptación.
  • content: proporciona los bytes exactos asociados al consentimiento.
  • if not content: rechaza una carga vacía antes de crear su intervalo de bytes.
  • Content-Type: Configurado application/octet-stream para la transferencia binaria.
  • Content-Length: establece el número exacto de bytes cargados.
  • Content-Range: describe el intervalo de bytes cargado y el total.
  • httpx.AsyncClient.put: cargue los bytes con una solicitud HTTP PUT .
  • response.status_code: acepta HTTP 200 o 201 y en caso contrario, fracasar.

Notificar al usuario

Notifique al usuario si la carga se realiza correctamente para que pueda abrir o descargar el archivo almacenado. Envía un mensaje que FileInfoCard contenga el identificador del elemento de unidad, el tipo de archivo y la URL del archivo almacenado.

Después de una carga correcta, envíe un archivo adjunto de información de archivo:

{
  "attachments": [
    {
      "contentType": "application/vnd.microsoft.teams.card.file.info",
      "contentUrl": "https://contoso.sharepoint.com/personal/user/Documents/Applications/file_example.txt",
      "name": "file_example.txt",
      "content": {
        "uniqueId": "1150D938-8870-4044-9F2C-5BBDEBA70C8C",
        "fileType": "txt"
      }
    }
  ]
}

Propiedades y valores clave:

  • contentType: usa el tipo de contenido de tarjeta de información de archivo que se muestra.
  • contentUrl: establece la dirección URL del archivo almacenado para el acceso del usuario.
  • uniqueId: establece el identificador del elemento de unidad de OneDrive o SharePoint.
  • fileType: establece la extensión de archivo notificada por la plataforma sin signos de puntuación.

Controlar los errores

Controle los errores conocidos del archivo SDK por separado de los errores de transporte y servicio. Para los usuarios agente, controle primero los errores de acceso a credenciales y a Graph, porque la recuperación de archivos depende de la identidad agente y de los permisos de plano técnico consentidos. El error de URL expirada se aplica a la ruta de acceso del bot que usa una dirección URL de descarga autorizada previamente.

Código de estado Código de error Descripción Acción del desarrollador
No aplicable FileCredentialException No hay ninguna credencial de Graph disponible para la recuperación de archivos de usuario agente. Compruebe los permisos del plano técnico, el consentimiento del administrador y la configuración de las credenciales.
HTTP 401 FileAccessException Microsoft Graph rechazó el token usado para recuperar el archivo. Actualice o corrija el token y compruebe el actor seleccionado.
HTTP 403 FileAccessException La identidad carece de consentimiento o acceso al elemento solicitado. Compruebe el consentimiento, el uso compartido, los permisos del plano técnico y el acceso a los elementos.
No aplicable FileUrlExpiredException La dirección URL del archivo preautorizado del bot expiró antes de recuperarse o volver a leerse. Pida al usuario que vuelva a adjuntar el archivo. Descargar una vez y volver a usar DownloadedFile.
No aplicable FileScopeNotSupportedException La API de archivos de alto nivel recibió un ámbito de conversación no admitido. Use el chat personal o recupere el archivo almacenado a través de Microsoft Graph.
No aplicable FileException Error en una operación de archivo SDK conocida por otro motivo. Mostrar un mensaje de usuario general y registrar diagnósticos saneados.
HTTP 5xx Error de transporte o servicio Microsoft Graph o el servicio de almacenamiento no pudieron completar la solicitud. Vuelva a intentarlo según las instrucciones del servicio y conserve la excepción original.

Una puede representar consentimiento que falta, acceso a 403 elemento que falta o un elemento inexistente. El SDK no expone un error de archivo no encontrado independiente para estas respuestas.

try
{
    DownloadedFile downloaded =
        await file.DownloadAsync(cancellationToken);
}
catch (FileCredentialException)
{
    await context.ReplyAsync(
        "The agent isn't configured to access this file.",
        cancellationToken);
}
catch (FileAccessException error)
{
    await context.ReplyAsync(
        $"The storage service denied access ({error.Status}).",
        cancellationToken);
}
catch (FileUrlExpiredException)
{
    await context.ReplyAsync(
        "That file link expired. Attach the file again.",
        cancellationToken);
}
catch (FileScopeNotSupportedException)
{
    await context.ReplyAsync(
        "File download isn't supported in this conversation.",
        cancellationToken);
}
catch (FileException)
{
    await context.ReplyAsync(
        "The file couldn't be read.",
        cancellationToken);
}

Tipos y valores de clave:

  • FileCredentialException: Gestionar la configuración de las credenciales de Graph del usuario agente que falta.
  • FileAccessException.Status: distingue los tokens rechazados del acceso denegado.
  • FileUrlExpiredException: Gestionar las direcciones URL de descarga del bot expiradas.
  • FileScopeNotSupportedException: Controlar la recuperación de grupos o canales no admitidos.
  • FileException: proporciona control de reserva para errores conocidos del SDK.
Código de estado Código de error Descripción Acción del desarrollador
No aplicable FileCredentialError No hay ninguna credencial de Graph disponible para la recuperación de archivos de usuario agente. Compruebe los permisos del plano técnico, el consentimiento del administrador y la configuración de las credenciales.
HTTP 401 o 403 FileAccessError Microsoft Graph rechazó el token o denegó el acceso al elemento. Inspeccionar statusy, a continuación, comprobar el token, el consentimiento, el uso compartido y el acceso a elementos.
No aplicable FileUrlExpiredError La dirección URL del archivo preautorizado del bot expiró antes de recuperarse o volver a leerse. Pida al usuario que vuelva a adjuntar el archivo. Descargue una vez y vuelva a usar el archivo descargado.
No aplicable FileScopeNotSupportedError La API de alto nivel recibió un ámbito de conversación no admitido. Use el chat personal o recupere el archivo almacenado a través de Microsoft Graph.
No aplicable FileError Error en una operación de archivo SDK conocida por otro motivo. Mostrar un mensaje de usuario general y registrar diagnósticos saneados.
HTTP 5xx Error de transporte o servicio Microsoft Graph o el almacenamiento no pudieron completar la solicitud. Vuelva a intentarlo según las instrucciones del servicio y conserve el error original.
try {
  const downloaded = await file.download();
} catch (error) {
  if (error instanceof FileCredentialError) {
    await send("The agent isn't configured to access this file.");
  } else if (error instanceof FileAccessError) {
    await send(`The storage service denied access (${error.status}).`);
  } else if (error instanceof FileUrlExpiredError) {
    await send('That file link expired. Attach the file again.');
  } else if (error instanceof FileScopeNotSupportedError) {
    await send("File download isn't supported in this conversation.");
  } else if (error instanceof FileError) {
    await send("The file couldn't be read.");
  } else {
    throw error;
  }
}

Tipos y valores de clave:

  • FileCredentialError: Gestionar las credenciales de Graph del usuario agente que faltan.
  • FileAccessError.status: distingue los tokens rechazados del acceso denegado.
  • FileUrlExpiredError: Gestionar las direcciones URL de descarga del bot expiradas.
  • FileScopeNotSupportedError: controlar ámbitos de conversación no admitidos.
  • FileError: proporciona control de reserva para errores conocidos del SDK.
Código de estado Código de error Descripción Acción del desarrollador
No aplicable FileCredentialError No hay ninguna credencial de Graph disponible para la recuperación de archivos de usuario agente. Compruebe los permisos del plano técnico, el consentimiento del administrador y la configuración de las credenciales.
HTTP 401 o 403 FileAccessError Microsoft Graph rechazó el token o denegó el acceso al elemento. Inspeccionar statusy, a continuación, comprobar el token, el consentimiento, el uso compartido y el acceso a elementos.
No aplicable FileUrlExpiredError La dirección URL del archivo preautorizado del bot expiró antes de recuperarse o volver a leerse. Pida al usuario que vuelva a adjuntar el archivo. Descargue una vez y vuelva a usar el archivo descargado.
No aplicable FileScopeNotSupportedError La API de alto nivel recibió un ámbito de conversación no admitido. Use el chat personal o recupere el archivo almacenado a través de Microsoft Graph.
No aplicable FileError Error en una operación de archivo SDK conocida por otro motivo. Mostrar un mensaje de usuario general y registrar diagnósticos saneados.
HTTP 5xx Error de transporte o servicio Microsoft Graph o el almacenamiento no pudieron completar la solicitud. Vuelva a intentarlo según las instrucciones del servicio y conserve el error original.
try:
    downloaded = await file.download()
except FileCredentialError:
    await ctx.reply("The agent isn't configured to access this file.")
except FileAccessError as error:
    await ctx.reply(
        f"The storage service denied access ({error.status})."
    )
except FileUrlExpiredError:
    await ctx.reply("That file link expired. Attach the file again.")
except FileScopeNotSupportedError:
    await ctx.reply(
        "File download isn't supported in this conversation."
    )
except FileError:
    await ctx.reply("The file couldn't be read.")

Tipos y valores de clave:

  • FileCredentialError: Gestionar las credenciales de Graph del usuario agente que faltan.
  • FileAccessError.status: distingue los tokens rechazados del acceso denegado.
  • FileUrlExpiredError: Gestionar las direcciones URL de descarga del bot expiradas.
  • FileScopeNotSupportedError: controlar ámbitos de conversación no admitidos.
  • FileError: proporciona control de reserva para errores conocidos del SDK.

Instrucciones de diseño y procedimientos recomendados

Aplique estas instrucciones para crear experiencias de archivo seguras y predecibles. Revíselas al diseñar controladores y antes de implementar la aplicación.

  • Informe a los usuarios si el agente recibió un archivo o está pidiendo cargar uno.
  • Confirme la recepción y carga correcta del archivo.
  • Explique por qué el bot solicita consentimiento de archivo antes de enviar un documento.
  • Controlar el consentimiento rechazado sin preguntar repetidamente al usuario.
  • Prefiera el descriptor de acceso de archivos del SDK de Teams a analizar manualmente los datos adjuntos de documentos.
  • Descargue una vez y vuelva a usar el archivo descargado al procesar contenido repetidamente.
  • Stream archivos grandes en lugar de almacenar en búfer el archivo completo en la memoria.
  • Desinfecta los nombres de archivo proporcionados por el cargador y usa destinos controlados por la aplicación.
  • Valide el contenido real en lugar de confiar en extensiones o tipos MIME notificados.
  • No registres bytes de archivos, credenciales, identificadores, ni direcciones URL de carga y descarga preautorizadas.
  • Aplique directivas de expiración y limpieza a las cargas pendientes de consentimiento de archivos.
  • Propagar la cancelación y controlar los errores de HTTP, credenciales, ámbito y expiración.

Vea también

Use estos recursos para explorar las API de archivo del SDK de Teams relacionadas, las imágenes en línea, la autenticación y la guía de mensajería.