Partekatu honen bidez:


Uso de datos de columna de archivo en Microsoft Dataverse

Las columnas de archivo de Microsoft Dataverse difieren de otras columnas del sistema que almacenan datos binarios porque no se pueden establecer directamente los valores en una operación de creación o actualización o recuperar los datos del archivo con el registro. Para crear, recuperar, actualizar o eliminar datos binarios para columnas de archivo, use los métodos descritos en este artículo. Obtenga información sobre cómo cargar, descargar y eliminar archivos mediante el SDK para .NET y la API web, incluida la compatibilidad con transferencias fragmentadas de archivos grandes.

Puede trabajar con datos de columna de archivo mediante varios métodos diferentes a través de la API web. Todos los métodos se admiten igualmente, por lo que elija el método que mejor funcione para usted. Dado que los archivos binarios pueden ser grandes, a menudo es necesario dividir el archivo en varios fragmentos (o bloques) que puede enviar o recibir secuencialmente o en paralelo para mejorar el rendimiento.

Columna de nombre de archivo

Cada columna de archivo está respaldada por una columna de cadena de solo lectura que contiene el nombre del archivo. El nombre de esquema de esta columna tiene el mismo nombre que la columna de archivo, pero con _Name anexado a ella. Por lo tanto, si el nombre del esquema es sample_FileColumn, la columna de cadena auxiliar es sample_FileColumn_Name. El nombre lógico de la columna auxiliar es sample_filecolumn_name.

Nota

La columna de nombre de archivo no aparece en el diseñador de Power Apps .

Relación con la tabla FileAttachment

Al crear una columna de archivo para una tabla, también se crea una nueva relación uno a varios entre esa tabla y la FileAttachment tabla. El nombre de la relación es {table logical name}_FileAttachments. Por ejemplo, si la columna de archivo forma parte de la tabla de cuentas, el nombre de la relación es account_FileAttachments.

Puede usar esta relación para devolver más datos sobre la columna de archivo y cualquier otra columna de archivo para la tabla. Para obtener más información, consulte Recuperación de información adicional sobre los archivos de un registro.

Comportamiento al recuperar

Al recuperar un registro e incluir una columna de archivo, el valor devuelto es un identificador único para el archivo. Puede usar este valor para eliminar el archivo mediante el DeleteFile mensaje . No hay otro uso para esta ID que no sea verificar si la columna tiene un valor. Para obtener más información, vea Usar el mensaje DeleteFile.

En los ejemplos siguientes se muestra lo que puede esperar al recuperar datos de columnas de archivo, como lo haría con otras columnas.

Estos ejemplos recuperan las columnas name, sample_filecolumn, y sample_filecolumn_name para un registro de cuenta:

static void RetrieveAccountRecordWithFileColumns(
    IOrganizationService service,
    Guid accountid) 
{

   Entity account = service.Retrieve(
         "account", 
         accountid, 
         new ColumnSet("name", "sample_filecolumn", "sample_filecolumn_name"));

   Console.WriteLine($"name: {account["name"]}");
   Console.WriteLine($"sample_filecolumn: {account["sample_filecolumn"]}");
   Console.WriteLine($"sample_filecolumn_name: {account["sample_filecolumn_name"]}");
}

Salida:

name: Contoso Ltd.
sample_filecolumn: <file id>
sample_filecolumn_name: 25mb.pdf

Más información:

Recuperar información adicional sobre los archivos de un registro

Puede usar la relación entre la tabla de columnas de archivo y la FileAttachment tabla para devolver información sobre todas las columnas de archivo asociadas a esa fila de tabla.

El método estático RetrieveAccountRecordWithFileData musetra cómo devolver información sobre todas las columnas del archivo que contienen datos relacionados con el registro account con el valor coincidente accountid.

static void RetrieveAccountRecordWithFileData(
    IOrganizationService service, 
    Guid accountid)
{
    // Create query for related records
    var relationshipQueryCollection = new RelationshipQueryCollection {
        {
            new Relationship("account_FileAttachments"),
            new QueryExpression("fileattachment"){
                ColumnSet = new ColumnSet(
                                "createdon",
                                "mimetype",
                                "filesizeinbytes",
                                "filename",
                                "regardingfieldname",
                                "fileattachmentid")
            }
        }
    };

    // Include the related query with the Retrieve Request
    RetrieveRequest request = new RetrieveRequest
    {
        ColumnSet = new ColumnSet("accountid"),
        RelatedEntitiesQuery = relationshipQueryCollection,
        Target = new EntityReference("account", accountid)
    };

    // Send the request
    RetrieveResponse response = (RetrieveResponse)service.Execute(request);

    //Display related FileAttachment data for the account record
    response.Entity.RelatedEntities[new Relationship("account_FileAttachments")]
        .Entities.ToList().ForEach(e =>
        {
            Console.WriteLine($"createdon: {e.FormattedValues["createdon"]}");
            Console.WriteLine($"mimetype: {e["mimetype"]}");
            Console.WriteLine($"filesizeinbytes: {e.FormattedValues["filesizeinbytes"]}");
            Console.WriteLine($"filename: {e["filename"]}");
            Console.WriteLine($"regardingfieldname: {e["regardingfieldname"]}");
            Console.WriteLine($"fileattachmentid: {e["fileattachmentid"]}");
        });
}

Salida:

En este caso, hay una sola columna de archivo en la tabla de cuentas denominada sample_filecolumn, y estos son los datos sobre el archivo almacenado en esa columna.

createdon: 10/22/2022 2:01 PM
mimetype: application/pdf
filesizeinbytes: 25,870,370
filename: 25mb.pdf
regardingfieldname: sample_filecolumn
fileattachmentid: 63a6afb7-4c52-ed11-bba1-000d3a9933c9

Más información:

Cargar archivos

Puede cargar archivos en una columna de archivo de tres maneras diferentes:

  • Usar mensajes de Dataverse disponibles tanto para el SDK como para la Web API
  • Carga de un archivo en una sola solicitud mediante la API web
  • Carga del archivo en fragmentos mediante la API web

Nota

Usar mensajes de Dataverse para subir un archivo

Puede usar mensajes de Dataverse mediante el SDK para .NET o la API web. Cargar un archivo de esta manera requiere el uso de un conjunto de tres mensajes:

Mensaje Descripción
InitializeFileBlocksUpload Utilice este mensaje para indicar la columna en la que desea cargar un archivo. Devuelve un token de continuación de archivo que puede usar para subir el archivo en bloques mediante el mensaje UploadBlock y con CommitFileBlocksUpload.
UploadBlock Divida su archivo en bloques y genere un blockid para cada bloque. A continuación, realice varias solicitudes hasta que se envíen todos los bloques junto con el token de continuación de archivo.
CommitFileBlocksUpload Después de enviar solicitudes para todos los bloques mediante UploadBlock, use este mensaje para confirmar la operación de carga enviando:
- La lista de IDs de bloques generados
- El nombre del archivo
- El tipo MIME del archivo
- El token de continuación del archivo

Para cargar un archivo o una imagen, use una función como la siguiente que usa las clases InitializeFileBlocksUploadRequest, UploadBlockRequest y CommitFileBlocksUploadRequest .

/// <summary>
/// Uploads a file or image column value
/// </summary>
/// <param name="service">The service</param>
/// <param name="entityReference">A reference to the record with the file or image column</param>
/// <param name="fileAttributeName">The name of the file or image column</param>
/// <param name="fileInfo">Information about the file or image to upload.</param>
/// <param name="fileMimeType">The mime type of the file or image, if known.</param>
/// <returns></returns>
static Guid UploadFile(
         IOrganizationService service,
         EntityReference entityReference,
         string fileAttributeName,
         FileInfo fileInfo,
         string fileMimeType = null)
{

   // Initialize the upload
   InitializeFileBlocksUploadRequest initializeFileBlocksUploadRequest = new()
   {
         Target = entityReference,
         FileAttributeName = fileAttributeName,
         FileName = fileInfo.Name
   };

   var initializeFileBlocksUploadResponse =
         (InitializeFileBlocksUploadResponse)service.Execute(initializeFileBlocksUploadRequest);

   string fileContinuationToken = initializeFileBlocksUploadResponse.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);
   }

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

   // Commit the upload
   CommitFileBlocksUploadRequest commitFileBlocksUploadRequest = new()
   {
         BlockList = blockIds.ToArray(),
         FileContinuationToken = fileContinuationToken,
         FileName = fileInfo.Name,
         MimeType = fileMimeType
   };

   var commitFileBlocksUploadResponse =
         (CommitFileBlocksUploadResponse)service.Execute(commitFileBlocksUploadRequest);

   return commitFileBlocksUploadResponse.FileId;

}

Más información:

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 de datos no se encuentra, se establece en application/octet-stream.

Carga de un archivo en una sola solicitud mediante la API web

Si el tamaño del archivo es inferior a 128 MB, puede cargar el archivo en una sola solicitud mediante la API web.

El siguiente ejemplo carga un archivo de texto llamado 4094kb.txt a la columna del archivo denominada sample_filecolumn en la tabla account para un registro con accountid igual a <accountid>.

Solicitud:

PATCH [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/octet-stream
x-ms-file-name: 4094kb.txt
Content-Length: 4191273

< binary content removed for brevity>

Respuesta:

HTTP/1.1 204 NoContent
OData-Version: 4.0

Ejemplo de PowerShell para cargar archivos en una sola solicitud

La siguiente función de PowerShell Set-FileColumn muestra cómo cargar un archivo en una sola solicitud mediante la API web.

Para más información sobre el uso de PowerShell y Visual Studio Code con dataverse Web API, consulte:

Esta función requiere una conexión que establezca los globales $baseURI y $baseHeaders. Establezca estos valores mediante la Connect función descrita en Creación de una función Connect.

<#
.SYNOPSIS
Sets a column value for a file in a specified table.

.DESCRIPTION
The Set-FileColumn function sets a column value for a file in a specified table. 
It uses a single request and can work with files less than 128 MB.

.PARAMETER setName
The entity set name of the table where the file is stored.

.PARAMETER id
The unique identifier of record.

.PARAMETER columnName
The logical name of the file column to set the value for.

.PARAMETER file
The path to the file to upload.

.EXAMPLE
Set-FileColumn `
   -setName 'accounts' `
   -id [System.Guid]::New('12345678-1234-1234-1234-1234567890AB') `
   -columnName 'new_filecolumn' `
   -file 'C:\Path\To\File.txt'
   
Sets the value of the 'new_filecolumn' column for the file with the specified ID 
in the account table to the contents of the File.txt file.

#>
function Set-FileColumn {
   param (
      [Parameter(Mandatory)]
      [string]
      $setName,
      [Parameter(Mandatory)]
      [System.Guid]
      $id,
      [Parameter(Mandatory)]
      [string]
      $columnName,
      [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
      [System.IO.FileInfo]$file
   )

   $uri = '{0}{1}({2})/{3}' -f $baseURI, $setName, $id, $columnName

   $patchHeaders = $baseHeaders.Clone()
   $patchHeaders.Add('Content-Type', 'application/octet-stream')
   $patchHeaders.Add('x-ms-file-name', $file.Name)

   $body = [System.IO.File]::ReadAllBytes($file.FullName)

   $FileUploadRequest = @{
      Uri     = $uri
      Method  = 'Patch'
      Headers = $patchHeaders
      Body    = $body
   }

   Invoke-RestMethod @FileUploadRequest
}

Carga del archivo en fragmentos mediante la API web

Para cargar el archivo en fragmentos mediante la API web, use el siguiente conjunto de solicitudes.

El siguiente ejemplo carga un archivo PDF llamado 25mb.pdf a la columna del archivo denominada sample_filecolumn en la tabla account para un registro con accountid igual a <accountid>.

Solicitud:

La primera solicitud debe incluir este encabezado: x-ms-transfer-mode: chunked.

Establezca el nombre de archivo mediante el x-ms-file-name parámetro de consulta.

PATCH [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn?x-ms-file-name=25mb.pdf HTTP/1.1
x-ms-transfer-mode: chunked
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json

Nota

También puede incluir el nombre de archivo como encabezado x-ms-file-name de solicitud, pero este enfoque no admite nombres de archivo fuera del conjunto de caracteres ASCII. Si usa el encabezado, tiene prioridad sobre el parámetro de consulta x-ms-file-name.

Respuesta:

HTTP/1.1 200 OK
Accept-Ranges: bytes
Location: [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn?sessiontoken=<sessiontoken value removed for brevity>
OData-Version: 4.0
x-ms-chunk-size: 4194304
Access-Control-Expose-Headers: x-ms-chunk-size

La respuesta de encabezado Ubicación incluye una URL para usar en solicitudes posteriores. Incluye un sessiontoken parámetro de consulta que indica que todas las solicitudes enviadas mediante su uso forman parte de la misma operación.

La respuesta incluye los siguientes encabezados.

Encabezado Descripción
x-ms-chunk-size Proporciona un tamaño de fragmento recomendado en bytes.
Accept-Ranges Indica que el servidor admite solicitudes parciales del cliente para descargas de archivos. El valor bytes indica que el valor del rango en las solicitudes posteriores debe estar en bytes.
Access-Control-Expose-Headers Indica que el valor de encabezado x-ms-chunk-size debe estar disponible para los scripts que se ejecutan en el navegador, en respuesta a una solicitud de origen cruzado.

Solicitud:

Las solicitudes subsiguientes deben utilizar el valor del encabezado Location devuelto por la primera solicitud para que el valor sessiontoken se incluya.

Cada solicitud debe contener esa parte del archivo en el cuerpo y los siguientes encabezados:

Encabezado Descripción
x-ms-file-name El nombre del archivo.
Tipo de contenido Establecer en application/octet-stream
Content-Range Con este formato:
<unit> <range-start>-<range-end>/<size>
El valor de la primera solicitud: bytes 0-4194303/25870370 indica que la medida está utilizando bytes. Esta solicitud incluye los primeros 4194303 bytes de un archivo que es de 25870370 bytes (casi 25 MB) en tamaño.
Cada solicitud posterior aumenta este valor hasta que se envía todo el archivo:
bytes 4194304-8388607/25870370
bytes 8388608-12582911/25870370
bytes 12582912-16777215/25870370
bytes 16777216-20971519/25870370
bytes 20971520-25165823/25870370
bytes 25165824-25870369/25870370
Content-Length Indica el tamaño del mensaje. En el ejemplo anterior, este valor para la última solicitud es 704546 en lugar de 4194304.
PATCH [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn?sessiontoken=<sessiontoken value removed for brevity> HTTP/1.1
x-ms-file-name: 25mb.pdf
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/octet-stream
Content-Range: bytes 0-4194303/25870370
Content-Length: 4194304

< byte[] content removed for brevity>

Para cada solicitud que contiene contenido parcial, la respuesta es 206 PartialContent.

Respuesta:

HTTP/1.1 206 PartialContent
OData-Version: 4.0

Para la solicitud final que incluye el último fragmento del archivo, la respuesta es 204 NoContent.

Respuesta:

HTTP/1.1 204 NoContent
OData-Version: 4.0

Ejemplo de PowerShell para cargar archivos en trozos

La siguiente función de PowerShell Set-FileColumnInChunks demuestra cómo cargar un archivo en trozos. Esta función requiere una conexión que establece las variables globales $baseURI y $baseHeaders mediante la función Connect descrita en Crear una función de conexión.

<#
.SYNOPSIS
Sets a column value for a file in a specified table.

.DESCRIPTION
The Set-FileColumnInChunks function sets a column value for a file in a specified table. 
It uses chunked file upload to efficiently upload large files.

.PARAMETER setName
The name of the table where the file is stored.

.PARAMETER id
The unique identifier of record.

.PARAMETER columnName
The logical name of the file column to set the value for.

.PARAMETER file
The path to the file to upload.

.EXAMPLE
Set-FileColumnInChunks `
   -setName 'accounts' `
   -id [System.Guid]::New('12345678-1234-1234-1234-1234567890AB') `
   -columnName 'new_filecolumn' `
   -file 'C:\Path\To\File.txt'
   
Sets the value of the 'new_filecolumn' column for the file with the specified ID in the account table to the contents of the File.txt file.

#>
function Set-FileColumnInChunks {
   param (
      [Parameter(Mandatory)]
      [string]
      $setName,
      [Parameter(Mandatory)]
      [System.Guid]
      $id,
      [Parameter(Mandatory)]
      [string]
      $columnName,
      [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
      [System.IO.FileInfo]$file
   )

   $uri = '{0}{1}({2})' -f $baseURI, $setName, $id
   $uri += '/{0}?x-ms-file-name={1}' -f $columnName, $file.Name

   $chunkHeaders = $baseHeaders.Clone()
   $chunkHeaders.Add('x-ms-transfer-mode', 'chunked')

   $InitializeChunkedFileUploadRequest = @{
      Uri     = $uri
      Method  = 'Patch'
      Headers = $chunkHeaders
   }

   Invoke-RestMethod @InitializeChunkedFileUploadRequest `
      -ResponseHeadersVariable rhv

   $locationUri = $rhv['Location'][0]
   $chunkSize = [int]$rhv['x-ms-chunk-size'][0]

   $bytes = [System.IO.File]::ReadAllBytes($file.FullName)

   for ($offset = 0; $offset -lt $bytes.Length; $offset += $chunkSize) {
         
      $count = if (($offSet + $chunkSize) -gt $bytes.Length) 
                  { $bytes.Length % $chunkSize } 
               else { $chunkSize }
      
      $lastByte = $offset + ($count - 1)

      $range = 'bytes {0}-{1}/{2}' -f $offset, $lastByte, $bytes.Length

      $contentHeaders = $baseHeaders.Clone()
      $contentHeaders.Add('Content-Range', $range)
      $contentHeaders.Add('Content-Type', 'application/octet-stream')
      $contentHeaders.Add('x-ms-file-name', $file.Name)

      $UploadFileChunkRequest = @{
         Uri     = $locationUri
         Method  = 'Patch'
         Headers = $contentHeaders
         Body    = [byte[]]$bytes[$offSet..$lastByte]
      }

      Invoke-RestMethod @UploadFileChunkRequest
   }
}

Comprobar el tamaño de archivo máximo

Antes de cargar un archivo, compruebe si el tamaño del archivo supera el tamaño máximo configurado almacenado en la MaxSizeInKB propiedad .

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

Nombre: unManagedidsattachmentinvalidfilesize
Código: 0x80044a02
Número: -2147202558
Mensaje: Attachment file size is too big.

Use los ejemplos siguientes para comprobar el tamaño máximo del archivo:

El método GetFileColumnMaxSizeInKb estático devuelve el valor MaxSizeInKB para una columna de archivo.

/// <summary>
/// Retrieves the MaxSizeInKb property of a file column.
/// </summary>
/// <param name="service">IOrganizationService</param>
/// <param name="entityLogicalName">The logical name of the table that has the column</param>
/// <param name="fileColumnLogicalName">The logical name of the file column.</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static int GetFileColumnMaxSizeInKb(
    IOrganizationService service, 
    string entityLogicalName, 
    string fileColumnLogicalName) 
{

   RetrieveAttributeRequest retrieveAttributeRequest = new() { 
         EntityLogicalName = entityLogicalName,
         LogicalName = fileColumnLogicalName
   };

   RetrieveAttributeResponse retrieveAttributeResponse;
   try
   {
         retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
   }
   catch (Exception)
   {
         throw;
   }

   if (retrieveAttributeResponse.AttributeMetadata is FileAttributeMetadata fileColumn)
   {
         return fileColumn.MaxSizeInKB.Value;
   }
   else
   {
         throw new Exception($"{entityLogicalName}.{fileColumnLogicalName} is not a file column.");
   }
}

Más información:

Descargar archivos

Puede usar tres métodos diferentes para descargar archivos de una columna de archivo:

  • Usar mensajes de Dataverse disponibles tanto para el SDK como para la Web API
  • Descarga de un archivo en una sola solicitud mediante la API web
  • Descarga del archivo en fragmentos mediante la API web

Nota

También puede usar estos métodos para descargar columnas de imagen, pero hay algunas diferencias. Para obtener más información, consulte Descargar imágenes.

En entornos locales o cuando un entorno usa una clave autoadministrada (BYOK), el archivo no está en el almacenamiento de archivos. Cuando un archivo no está en el almacenamiento de archivos, no se admite la descarga en varios fragmentos. La clase InitializeFileBlocksDownloadResponse ComplexType e InitializeFileBlocksDownloadResponse tienen una IsChunkingSupported propiedad que indica si el archivo se puede descargar en varios fragmentos o no. Si no se admite la fragmentación, el BlockLength valor se establece en el tamaño del archivo.

Al intentar descargar un fragmento parcial cuando IsChunkingSupported se establece en false, se produce este error:

Nombre: UploadingAndDownloadingInMultipleChunksNotSupported
Código: 0x80090017
Mensaje: Downloading in multiple chunks isn't supported for the files stored in the database.

Usar mensajes de Dataverse para descargar un archivo

Puede usar mensajes de Dataverse mediante el SDK para .NET o la API web. Descargar un archivo de esta manera requiere el uso de un conjunto de dos mensajes:

Mensaje Descripción
InitializeFileBlocksDownload Utilice este mensaje para indicar la columna desde la 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 DownloadBlock mensaje.
DownloadBlock Solicitar el tamaño del bloque, el valor de desplazamiento y el token de continuación del archivo.

Después de descargar todos los bloques, debe unirlos para crear todo el archivo descargado.

Puede usar una función como la siguiente para descargar un archivo o una imagen mediante el SDK y las clases InitializeFileBlocksDownloadRequest y DownloadBlockRequest .

/// <summary>
/// Downloads a file or image
/// </summary>
/// <param name="service">The service</param>
/// <param name="entityReference">A reference to the record with the file or image column</param>
/// <param name="attributeName">The name of the file or image column</param>
/// <returns></returns>
private static byte[] DownloadFile(
            IOrganizationService service,
            EntityReference entityReference,
            string attributeName)
{
   InitializeFileBlocksDownloadRequest initializeFileBlocksDownloadRequest = new()
   {
         Target = entityReference,
         FileAttributeName = attributeName
   };

   var initializeFileBlocksDownloadResponse =
         (InitializeFileBlocksDownloadResponse)service.Execute(initializeFileBlocksDownloadRequest);

   string fileContinuationToken = initializeFileBlocksDownloadResponse.FileContinuationToken;
   long fileSizeInBytes = initializeFileBlocksDownloadResponse.FileSizeInBytes;

   List<byte> fileBytes = new((int)fileSizeInBytes);

   long offset = 0;
   // If chunking is not supported, chunk size will be full size of the file.
   long blockSizeDownload = !initializeFileBlocksDownloadResponse.IsChunkingSupported ? fileSizeInBytes :  4 * 1024 * 1024;

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

Más información:

Descargar un archivo en una sola solicitud usando la API web

El siguiente ejemplo descarga un archivo de texto llamado 4094kb.txt de la columna del archivo denominada sample_filecolumn en la tabla account para un registro con accountid igual a <accountid>.

Solicitud:

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

Respuesta:

La respuesta incluye los siguientes encabezados.

Cabecera Descripción
x-ms-file-size Tamaño de archivo en bytes.
x-ms-file-name El nombre del archivo.
mimetype El tipo MIME del archivo.
Access-Control-Expose-Headers Indica que los valores de encabezado x-ms-file-size, x-ms-file-name y mimetype están disponibles para los scripts que se ejecutan en el navegador, en respuesta a una solicitud entre orígenes.
HTTP/1.1 200 OK
x-ms-file-size: 4191273
x-ms-file-name: 4094kb.txt
mimetype: text/plain
Access-Control-Expose-Headers: x-ms-file-size; x-ms-file-name; mimetype

< byte[] content removed for brevity. >

Descarga del archivo en fragmentos mediante la API web

Nota

El ejemplo siguiente funciona cuando IsChunkingSupported se establece en true. Si es falso, use Descargar un archivo en una sola solicitud mediante API web (Download a file in a single request using Web API).

Para descargar el archivo en fragmentos mediante la API web, use el siguiente conjunto de solicitudes.

El siguiente ejemplo descarga un archivo PDF llamado 25mb.pdf a la columna del archivo denominada sample_filecolumn en la tabla account para un registro con accountid igual a <accountid>.

Solicitud:

Use el encabezado Range para especificar el número de bytes que se van a devolver mediante este formato:
<unit>=<range-start>-<range-end>
Donde unit es bytes y range-start para la primera solicitud es 0.

No sabe cuántas iteraciones son necesarias para descargar todo el archivo hasta que obtenga la primera respuesta donde el x-ms-file-size encabezado de respuesta indica el tamaño del archivo.

Mientras que <range-start> sea más pequeño que el tamaño total del archivo, para cada solicitud subsiguiente incremente los valores <range-start> y <range-end> para solicitar el siguiente fragmento del archivo.

GET [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn/$value HTTP/1.1
Range: bytes=0-4194303
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json

Respuesta:

La respuesta incluye los siguientes encabezados:

Encabezado Descripción
x-ms-file-size Tamaño de archivo en bytes.
x-ms-file-name El nombre del archivo.
x-ms-chunk-size Proporciona un tamaño de fragmento recomendado en bytes.
mimetype El tipo MIME del archivo.
Access-Control-Expose-Headers Indica que los valores de x-ms-file-size encabezado, x-ms-file-name, x-ms-chunk-size, y mimetype deben estar disponibles para los scripts que se ejecutan en el navegador, en respuesta a una solicitud entre orígenes.
HTTP/1.1 206 PartialContent
x-ms-file-size: 25870370
x-ms-file-name: 25mb.pdf
x-ms-chunk-size: 4194304
mimetype: application/pdf
Access-Control-Expose-Headers: x-ms-file-size; x-ms-file-name; x-ms-chunk-size; mimetype
OData-Version: 4.0

< byte[] content removed for brevity. >

Eliminar archivos

Puede eliminar archivos en una columna de archivo mediante cualquiera de los métodos siguientes:

  • Use el mensaje de Dataverse DeleteFile , que está disponible para el SDK y la API web.
  • Envíe una solicitud DELETE mediante la API web a la columna de archivo del registro.

Usa el mensaje DeleteFile

Mediante el uso del identificador único devuelto de CommitFileBlocksUploadResponse.FileId o recuperado de la columna tal como se describe en Comportamiento al recuperar, puede eliminar el archivo mediante el mensaje DeleteFile.

Use una función como el ejemplo siguiente para eliminar un archivo mediante el identificador único y la clase DeleteFileRequest.

static Guid DeleteFile(IOrganizationService service, Guid fileId)
{
   DeleteFileRequest deleteFileRequest = new()
   {
      FileId = fileId
   };
   service.Execute(deleteFileRequest);
}

Enviar solicitud de ELIMINAR a la columna de archivo

Mediante la API web, puede eliminar un archivo mediante el envío de una DELETE solicitud a la ubicación del recurso de archivo.

El siguiente ejemplo elimina los datos de archivo de una columna llamada sample_filecolumn en la tabla account para un registro con accountid igual a <accountid>.

Solicitud:

DELETE [Organization Uri]/api/data/v9.2/accounts(<accountid>)/sample_filecolumn HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json

Respuesta:

HTTP/1.1 204 NoContent
OData-Version: 4.0

Más información: Eliminar un solo valor de propiedad

Consulte también

Información general sobre imágenes y archivos
Tipos de datos de columna > Columnas de ficheros
Trabajar con definiciones de columna de archivo mediante código
Ejemplo: Operaciones de archivo usando la SDK de Dataverse para .NET
Ejemplo: Operaciones de archivo con Dataverse Web API.