Compartir a través de


Usar datos de archivo con registros de Adjuntos y Notas

Las tablas de datos adjuntos (ActivityMimeAttachment) y notas (anotación) contienen columnas de cadenas especiales que almacenan datos de archivos. Estas tablas existían antes que las columnas de archivos o imágenes, por lo que funcionan de manera diferente a esas tablas.

  • Los datos del archivo binario se almacenan como valores de cadena codificados en Base64 en columnas de cadena. Los archivos adjuntos se almacenan en la columna y las notas se almacenan en la columna .
  • Los datos del nombre del archivo se almacenan en la columna .
  • Los datos de tipo MIME se almacenan en la columna .

Dado que , , y forman parte de los datos del registro adjunto o de nota, actualice estas tres columnas junto con cualquier otro valor.

Puede obtener y establecer directamente los valores de las columnas y como cadenas codificadas en Base64. Establecer estos valores debería estar bien siempre que los archivos no sean demasiado grandes, por ejemplo, menos de 4 MB. De forma predeterminada, la longitud máxima es 5 MB. Puede configurar estas columnas para aceptar archivos de hasta 128 MB. Al aumentar el tamaño máximo de archivo y trabajar con archivos más grandes, use los mensajes proporcionados para dividir los archivos en fragmentos más pequeños al cargar o descargar archivos. Para obtener información sobre cómo recuperar o cambiar los límites de tamaño de archivo, consulte Límites de tamaño de archivo.

Archivos de datos adjuntos

Un adjunto es un archivo que está asociado con una actividad de correo electrónico, ya sea directamente o a través de una Plantilla de correo electrónico (Plantilla). Puede asociar varios datos adjuntos a la actividad o plantilla. Puede reutilizar archivos adjuntos configurando el valor para hacer referencia a otro archivo adjunto existente en lugar de configurar las propiedades , y .

Otras tablas de Dataverse denominadas archivo adjunto

No confunda attachment (ActivityMimeAttachment) con activityfileattachment, que admite archivos asociados a la tabla Post .

Dentro del esquema de Dataverse, también hay una tabla pública con el nombre , que se expone en la API web como attachment EntityType. Puede consultar esta tabla, que refleja los datos de la tabla . Pero no admite operaciones de crear, recuperar, actualizar o eliminar. Esta tabla no aparece en el diseñador Power Apps.

Cargar archivos adjuntos

Utilice los mensajes , y para cargar archivos grandes para adjuntar.

Importante

Solo puede usar estos mensajes para crear un nuevo archivo adjunto. Si intenta usarlos para actualizar los datos adjuntos existentes, obtendrá un error que indica que el registro ya existe.

El siguiente método estático muestra cómo crear un archivo adjunto mediante las clases , y para devolver una con las propiedades y .

static CommitAttachmentBlocksUploadResponse UploadAttachment(
   IOrganizationService service,
   Entity attachment,
   FileInfo fileInfo,
   string fileMimeType = null)
{
   if (attachment.LogicalName != "activitymimeattachment")
   {
         throw new ArgumentException(
            "The attachment parameter must be an activitymimeattachment entity.",
            nameof(attachment));
   }

   // body value in activitymimeattachment not needed. Remove if found.
   if (attachment.Contains("body"))
   {
         attachment.Attributes.Remove("body");
   }

   // Try to get the mimetype if not provided.
   if (string.IsNullOrEmpty(fileMimeType))
   {
         var provider = new FileExtensionContentTypeProvider();

         if (!provider.TryGetContentType(fileInfo.Name, out fileMimeType))
         {
            fileMimeType = "application/octet-stream";
         }
   }
   // Don't overwrite mimetype value if it exists
   if (!attachment.Contains("mimetype"))
   {
         attachment["mimetype"] = fileMimeType;
   }

   // Initialize the upload
   InitializeAttachmentBlocksUploadRequest initializeRequest = new()
   {
         Target = attachment
   };

   var initializeResponse =
         (InitializeAttachmentBlocksUploadResponse)service.Execute(initializeRequest);

   string fileContinuationToken = initializeResponse.FileContinuationToken;

   // Capture blockids while uploading
   List<string> blockIds = new();

   using Stream uploadFileStream = fileInfo.OpenRead();

   int blockSize = 4 * 1024 * 1024; // 4 MB

   byte[] buffer = new byte[blockSize];
   int bytesRead = 0;

   long fileSize = fileInfo.Length;

   // The number of iterations that will be required:
   // int blocksCount = (int)Math.Ceiling(fileSize / (float)blockSize);
   int blockNumber = 0;

   // While there is unread data from the file
   while ((bytesRead = uploadFileStream.Read(buffer, 0, buffer.Length)) > 0)
   {
         // The file or final block may be smaller than 4MB
         if (bytesRead < buffer.Length)
         {
            Array.Resize(ref buffer, bytesRead);
         }

         blockNumber++;

         string blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));

         blockIds.Add(blockId);

         // Prepare the request
         UploadBlockRequest uploadBlockRequest = new()
         {
            BlockData = buffer,
            BlockId = blockId,
            FileContinuationToken = fileContinuationToken,
         };

         // Send the request
         service.Execute(uploadBlockRequest);
   }

   // Commit the upload
   CommitAttachmentBlocksUploadRequest commitRequest = new()
   {
         BlockList = blockIds.ToArray(),
         FileContinuationToken = fileContinuationToken,
         Target = attachment
   };
   
      return  (CommitAttachmentBlocksUploadResponse)service.Execute(commitRequest);

}

Para obtener más información, consulte:

Nota

Este método de ejemplo incluye algo de lógica para tratar de obtener el Tipo de MIME del archivo usando el Método FileExtensionContentTypeProvider.TryGetContentType(String, String) si no se proporciona. Si el tipo no se encuentra, se establece en .

Descargar los archivos de datos adjuntos

Puede descargar un archivo adjunto en una sola operación mediante la API web o en fragmentos mediante el SDK o la API web.

Descarga de archivos adjuntos en una sola operación mediante la API web

Mediante la API web, puede descargar un archivo adjunto en una sola operación.

A diferencia de la recuperación de columnas de archivos, este método no proporciona información sobre el tamaño del archivo, el nombre del archivo o el tipo MIME.

Solicitud:

GET [Organization Uri]/api/data/v9.2/activitymimeattachments(<activitymimeattachmentid>)/body/$value HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json

Respuesta:

HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: text/plain

<Base64 string content removed for brevity>

Para obtener más información, consulte:

  • Descargar un archivo en una sola solicitud usando la API web
  • Recuperar el valor sin procesar de una propiedad

Descargar los archivos de datos adjuntos en fragmentos

Para recuperar el archivo en fragmentos, use los siguientes mensajes con el SDK o la API web:

Mensaje Descripción
InitializeAttachmentBlocksDownload Especifica el registro de Nota del que desea descargar un archivo. Devuelve el tamaño del archivo en bytes y un token de continuación de archivo que puede usar para descargar el archivo en bloques usando el mensaje .
DownloadBlock Solicita el tamaño del bloque, el valor de compensación y el token de continuación del archivo.

Después de descargar todos los bloques, únelos para crear el archivo descargado completo.

El siguiente método estático muestra cómo descargar datos adjuntos mediante el SDK con las clases InitializeAttachmentBlocksDownloadRequest y DownloadBlockRequest . Esta función devuelve los datos y el nombre del archivo.

static (byte[] bytes, string fileName) DownloadAttachment(
   IOrganizationService service,
   EntityReference target)
{
   if (target.LogicalName != "activitymimeattachment")
   {
         throw new ArgumentException(
            "The target parameter must refer to an activitymimeattachment record.",
            nameof(target));
   }

   InitializeAttachmentBlocksDownloadRequest initializeRequest = new()
   {
         Target = target
   };

   var response =
         (InitializeAttachmentBlocksDownloadResponse)service.Execute(initializeRequest);

   string fileContinuationToken = response.FileContinuationToken;
   int fileSizeInBytes = response.FileSizeInBytes;
   string fileName = response.FileName;

   List<byte> fileBytes = new(fileSizeInBytes);

   long offset = 0;
   long blockSizeDownload = 4 * 1024 * 1024; // 4 MB

   // File size may be smaller than defined block size
   if (fileSizeInBytes < blockSizeDownload)
   {
         blockSizeDownload = fileSizeInBytes;
   }

   while (fileSizeInBytes > 0)
   {
         // Prepare the request
         DownloadBlockRequest downLoadBlockRequest = new()
         {
            BlockLength = blockSizeDownload,
            FileContinuationToken = fileContinuationToken,
            Offset = offset
         };

         // Send the request
         var downloadBlockResponse =
                  (DownloadBlockResponse)service.Execute(downLoadBlockRequest);

         // Add the block returned to the list
         fileBytes.AddRange(downloadBlockResponse.Data);

         // Subtract the amount downloaded,
         // which may make fileSizeInBytes < 0 and indicate
         // no further blocks to download
         fileSizeInBytes -= (int)blockSizeDownload;
         // Increment the offset to start at the beginning of the next block.
         offset += blockSizeDownload;
   }

   return (fileBytes.ToArray(), fileName);
}

Para obtener más información, consulte:

Archivos de anotación

Una nota es un registro asociado a una fila de tabla que contiene texto y puede tener un archivo adjunto. Solo las tablas con EntityMetadata.HasNotes establecidas en true admiten notas asociadas.

Cargar archivos de anotación

Utilice los mensajes , y para cargar archivos para notas.

La anotación que pasa como el parámetro para estos mensajes debe tener un valor . Este valor es cómo se actualizan los registros de anotación existentes.

Normalmente, permite que Dataverse genere los valores de identificador únicos al crear nuevos registros, pero no puede hacerlo con estos mensajes. Para crear una nueva anotación mediante estos mensajes, genere un nuevo valor para establecerlo como valor en lugar de permitir que Dataverse genere el valor.

El siguiente método estático muestra cómo crear o actualizar una nota con un archivo mediante las clases , y . Devuelve un registro con las propiedades y .

static CommitAnnotationBlocksUploadResponse UploadNote(
   IOrganizationService service,
   Entity annotation,
   FileInfo fileInfo,
   string? fileMimeType = null)
{

   if (annotation.LogicalName != "annotation")
   {
         throw new ArgumentException(
            message: "The annotation parameter must be an annotation entity",
            paramName: nameof(annotation));
   }
   if (!annotation.Attributes.Contains("annotationid") || annotation.Id != Guid.Empty)
   {
         throw new ArgumentException(
            message: "The annotation parameter must include a valid annotationid value.",
            paramName: nameof(annotation));
   }

   // documentbody value in annotation not needed. Remove if found.
   if (annotation.Contains("documentbody"))
   {
         annotation.Attributes.Remove("documentbody");
   }

   // Try to get the mimetype if not provided.
   if (string.IsNullOrEmpty(fileMimeType))
   {
         var provider = new FileExtensionContentTypeProvider();

         if (!provider.TryGetContentType(fileInfo.Name, out fileMimeType))
         {
            fileMimeType = "application/octet-stream";
         }
   }
   // Don't override what might be included in the annotation.
   if (!annotation.Contains("mimetype")) {
         annotation["mimetype"] = fileMimeType;
   }
   
   // Initialize the upload
   InitializeAnnotationBlocksUploadRequest initializeRequest = new()
   {
         Target = annotation
   };

   var initializeResponse =
         (InitializeAnnotationBlocksUploadResponse)service.Execute(initializeRequest);

   string fileContinuationToken = initializeResponse.FileContinuationToken;

   // Capture blockids while uploading
   List<string> blockIds = new();

   using Stream uploadFileStream = fileInfo.OpenRead();

   int blockSize = 4 * 1024 * 1024; // 4 MB

   byte[] buffer = new byte[blockSize];
   int bytesRead = 0;

   long fileSize = fileInfo.Length;

   // The number of iterations that will be required:
   // int blocksCount = (int)Math.Ceiling(fileSize / (float)blockSize);
   int blockNumber = 0;

   // While there is unread data from the file
   while ((bytesRead = uploadFileStream.Read(buffer, 0, buffer.Length)) > 0)
   {
         // The file or final block may be smaller than 4MB
         if (bytesRead < buffer.Length)
         {
            Array.Resize(ref buffer, bytesRead);
         }

         blockNumber++;
         // Generates base64 string blockId values based on a Guid value so they are always the same length.
         string blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));

         blockIds.Add(blockId);

         // Prepare the request
         UploadBlockRequest uploadBlockRequest = new()
         {
            BlockData = buffer,
            BlockId = blockId,
            FileContinuationToken = fileContinuationToken,
         };

         // Send the request
         service.Execute(uploadBlockRequest);
   }

   // Commit the upload
   CommitAnnotationBlocksUploadRequest commitRequest = new()
   {
         BlockList = blockIds.ToArray(),
         FileContinuationToken = fileContinuationToken,
         Target = annotation
   };

      return  (CommitAnnotationBlocksUploadResponse)service.Execute(commitRequest);
}

Para obtener más información, consulte:

Nota

Este método de ejemplo incluye algo de lógica para tratar de obtener el Tipo de MIME del archivo usando el Método FileExtensionContentTypeProvider.TryGetContentType(String, String) si no se proporciona. Si el tipo no se encuentra, se establece en .

Descargar archivos de anotación

Puede descargar un archivo note en un solo paso mediante la API web o en fragmentos mediante el SDK o la API web.

Descarga de archivos de anotación en un solo paso mediante la API web

Mediante la API web, puede descargar un archivo note en un solo paso:

A diferencia de la recuperación de columnas de archivos, este método no proporciona información sobre el tamaño del archivo, el nombre del archivo o el tipo MIME.

Solicitud:

GET [Organization Uri]/api/data/v9.2/annotations(<annotationid>)/documentbody/$value HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json

Respuesta:

HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: text/plain

<Base64 string content removed for brevity>

Para obtener más información, consulte:

  • Descargar un archivo en una sola solicitud usando la API web
  • Recuperar el valor sin procesar de una propiedad

Descargar los archivos de anotación en fragmentos

Para recuperar el archivo en fragmentos, use los siguientes mensajes con el SDK o la API web:

Mensaje Descripción
InitializeAnnotationBlocksDownload Especifica el registro de Nota del que desea descargar un archivo. Devuelve el tamaño del archivo en bytes y un token de continuación de archivo que puede usar para descargar el archivo en bloques mediante el mensaje.
DownloadBlock Solicita el tamaño del bloque, el valor de compensación y el token de continuación del archivo.

Después de descargar todos los bloques, únelos para crear el archivo descargado completo.

El siguiente método estático muestra cómo descargar una nota mediante el SDK con las clases InitializeAnnotationBlocksDownloadRequest y DownloadBlockRequest . Esta función devuelve los datos y el nombre del archivo.

static (byte[] bytes, string fileName) DownloadNote(
    IOrganizationService service,
    EntityReference target)
{
if (target.LogicalName != "annotation")
{
      throw new ArgumentException("The target parameter must refer to an note record.", nameof(target));
}

InitializeAnnotationBlocksDownloadRequest initializeRequest = new()
{
      Target = target
};

var response =
      (InitializeAnnotationBlocksDownloadResponse)service.Execute(initializeRequest);

string fileContinuationToken = response.FileContinuationToken;
int fileSizeInBytes = response.FileSizeInBytes;
string fileName = response.FileName;

List<byte> fileBytes = new(fileSizeInBytes);

long offset = 0;
long blockSizeDownload = 4 * 1024 * 1024; // 4 MB

// File size may be smaller than defined block size
if (fileSizeInBytes < blockSizeDownload)
{
      blockSizeDownload = fileSizeInBytes;
}

while (fileSizeInBytes > 0)
{
      // Prepare the request
      DownloadBlockRequest downLoadBlockRequest = new()
      {
            BlockLength = blockSizeDownload,
            FileContinuationToken = fileContinuationToken,
            Offset = offset
      };

      // Send the request
      var downloadBlockResponse =
                  (DownloadBlockResponse)service.Execute(downLoadBlockRequest);

      // Add the block returned to the list
      fileBytes.AddRange(downloadBlockResponse.Data);

      // Subtract the amount downloaded,
      // which may make fileSizeInBytes < 0 and indicate
      // no further blocks to download
      fileSizeInBytes -= (int)blockSizeDownload;
      // Increment the offset to start at the beginning of the next block.
      offset += blockSizeDownload;
}

return (fileBytes.ToArray(), fileName);
}

Para obtener más información, consulte:

Límites de tamaño de archivo

La columna Organization.MaxUploadFileSize especifica el tamaño máximo permitido de un archivo en bytes para un archivo adjunto y una nota, así como para otros tipos de datos, como los archivos de recursos web utilizados para aplicaciones basadas en modelos. El límite máximo de tamaño de archivo de carga se aplica al tamaño del archivo en codificación Base64. Una codificación Base64 produce una cadena que es más grande que los datos del archivo original.

El tamaño predeterminado es de 5 MB (5 242 880 bytes) y el valor máximo es de 128 MB (131 072 000 bytes). Puede establecer este valor en la configuración de correo electrónico del entorno. Para obtener más información, consulte Administrar la configuración de correo electrónico.

Si intenta cargar un archivo demasiado grande, recibirá el siguiente mensaje de error:

Nombre:
Código:
Número:
Mensaje:

Recuperar el tamaño máximo de archivo de carga

Puede recuperar el tamaño máximo del archivo de carga de varias maneras.

Use un método estático como el método siguiente para obtener el valor.

public static int GetMaxUploadFileSize(IOrganizationService service) {

   QueryExpression query = new("organization") { 
         ColumnSet = new ColumnSet("maxuploadfilesize")
   };

   EntityCollection organizations = service.RetrieveMultiple(query);

   // There is only one row in organization table
   return (int)organizations.Entities.FirstOrDefault()["maxuploadfilesize"];
}

Para obtener más información, consulte:

  • Use el SDK para .NET
  • Método IOrganizationService.RetrieveMultiple
  • Crear consultas con QueryExpression

Cambiar el tamaño máximo de archivo de carga

Establezca el valor de dos maneras.

Utilice un método estático como el siguiente para establecer el tamaño máximo del archivo de carga.

public static void SetMaxUploadFileSize(
    IOrganizationService service, 
    int maxUploadFileSizeInBytes)
{
   if (maxUploadFileSizeInBytes > 131072000 || maxUploadFileSizeInBytes < 1) {
         throw new ArgumentOutOfRangeException(nameof(maxUploadFileSizeInBytes), 
         "The maxUploadFileSizeInBytes parameter must be less than 131072000 bytes and greater than 0 bytes.");
   }

   QueryExpression query = new("organization")
   {
         ColumnSet = new ColumnSet("organizationid")
   };

   EntityCollection organizations = service.RetrieveMultiple(query);

   // There is only one row in organization table
   Entity organization = organizations.Entities.FirstOrDefault();
   organization["maxuploadfilesize"] = maxUploadFileSizeInBytes;

   service.Update(organization);
}

Para obtener más información, consulte:

  • Use el SDK para .NET
  • Método IOrganizationService.RetrieveMultiple
  • Crear consultas con QueryExpression
  • Método IOrganizationService.Update

Consulte también

Información general sobre imágenes y archivos
Sample: operaciones de archivo con datos adjuntos y notas mediante el SDK de Dataverse para .NET
Ejemplo: operaciones con archivos adjuntos y anotaciones utilizando la API web de Dataverse