Usar datos de columna de archivo

Las columnas de archivo son diferentes de las otras columnas del sistema que pueden almacenar datos binarios porque no puede establecer los valores directamente en una operación de creación o actualización ni recuperar los datos del archivo con el registro. Debe usar los métodos descritos en este artículo para crear, recuperar, actualizar o eliminar datos binarios para columnas de archivos.

Hay varias formas diferentes de trabajar con datos de columnas de archivos mediante la API web. Todos los métodos son compatibles por igual. Elija el método que funcione mejor para usted. Debido a que los archivos binarios pueden ser grandes, con frecuencia es necesario dividir el archivo en varios fragmentos (o bloques) que se pueden enviar o recibir secuencialmente o en paralelo para mejorar el rendimiento.

Columna de nombre de archivo

Cada columna de archivo tiene una columna de cadena de solo lectura que contiene el nombre del archivo. El nombre de esquema para esta columna tiene el mismo nombre que la columna del archivo, pero tiene _Name anexado a ella. Entonces, si el nombre del esquema es sample_FileColumn, la columna de cadena de apoyo será sample_FileColumn_Name. El nombre lógico de la columna de apoyo será 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

Cuando se crea una columna de archivo para una tabla, se crea una nueva relación de uno a varios entre la tabla y la tabla FileAttachment. El nombre de la relación es {table logical name}_FileAttachments. Por ejemplo, si la columna del archivo es parte de la tabla de cuentas, el nombre de la relación será 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. Más información: Recuperar información adicional sobre archivos para un registro.

Comportamiento al recuperar

Cuando recupera un registro e incluye una columna de archivo, el valor devuelto será un identificador único para el archivo. Puede usar este valor para eliminar el archivo usando el mensaje DeleteFile. No hay otro uso para esta ID que no sea verificar si la columna tiene un valor. Más información: Usar el mensaje DeleteFile.

Los siguientes ejemplos muestran lo que puede esperar al recuperar datos de columnas de archivos 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

Nota

Debe solicitar explícitamente que la columna devuelva la identificación del archivo. Si utiliza ColumnSet.AllColumns a verdadero en su consulta, la columna del archivo no se devolverá. Si ha usado new ColumnSet(true) en la función anterior, el resultado sería un System.Collections.Generic.KeyNotFoundException.

Más información:

Recuperar información adicional sobre archivos para un registro

Puede utilizar la relación entre la tabla de columnas del archivo y la tabla FileAttachment para devolver información sobre todas las columnas del archivo asociadas a esa fila de la 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

Hay tres formas diferentes de cargar archivos en una columna de archivos:

  • Usar mensajes de Dataverse disponibles tanto para el SDK Webcomo para la API web
  • Cargar un archivo en una sola solicitud usando la API web
  • Cargar el archivo en fragmentos utilizando la API web

Nota

Usar mensajes de Dataverse para subir un archivo

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

Publicación 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 cargar el archivo en bloques usando el mensaje UploadBlock y con CommitFileBlocksUpload.
UploadBlock Divida su archivo en bloques y genere un blockid para cada bloque. Luego haga varias solicitudes hasta que todos los bloques se hayan enviado junto con el token de continuación del archivo.
CommitFileBlocksUpload Después de haber enviado solicitudes para todos los bloques usando UploadBlock, use este mensaje para confirmar la operación de carga enviando:
- La lista de id. de bloques generados
- El nombre del archivo
- El tipo MIME del archivo
- El token de continuación del archivo

Puede usar una función como la siguiente para cargar un archivo o imagen usando 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.

Cargar un archivo en una sola solicitud usando 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 demuestra cómo cargar un archivo en una sola solicitud utilizando Web API.

Obtenga más información sobre el uso de PowerShell y Visual Studio Code con la API web Dataverse:

Esta función requiere una conexión que establezca el valor global $baseURI y $baseHeaders que se configuran usando la función Connect descrita en Crear 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
}

Cargar el archivo en fragmentos utilizando la API web

Para cargar su archivo en fragmentos usando 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 del archivo con el parámetro de consulta x-ms-file-name.

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

El nombre del archivo también se puede incluir como encabezado de solicitud x-ms-file-name, pero esto no admitirá nombres de archivo fuera del conjunto de caracteres ASCII. Si se utiliza el encabezado, tendrá 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 parámetro de consulta sessiontoken que indica que todas las solicitudes enviadas a través de él 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 Configurar 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 de 25870370 bytes (casi 25 MB) de tamaño.
Cada solicitud posterior verá aumentar este valor hasta que se haya enviado el archivo completo:
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 será 704546 en vez 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 contenga contenido parcial, la respuesta será 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 será 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 establezca el valor global $baseURI y $baseHeaders que se configuran usando la función Connect descrita en Crear una función Connect.

<#
.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, puede verificar si el tamaño del archivo excede el Tamaño máximo de archivo configurado y almacenado en la propiedad MaxSizeInKB.

Si intenta cargar un archivo que es demasiado grande, obtendrá el siguiente error:

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

Puede utilizar los siguientes ejemplos para comprobar el tamaño máximo de 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

Hay tres métodos diferentes de descargar archivos desde una columna de archivos:

  • Usar mensajes de Dataverse disponibles tanto para el SDK Webcomo para la API web
  • Descargar un archivo en una sola solicitud usando la API web
  • Descargar el archivo en fragmentos utilizando la API web

Nota

Estos métodos también se pueden usar para descargar columnas de imágenes, pero existen algunas diferencias. Más información: Descargar imágenes

Para entornos local o cuando un entorno usa la Clave auto administrada (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. InitializeFileBlocksDownloadResponse ComplexType y la clase InitializeFileBlocksDownloadResponse tienen una propiedad IsChunkingSupported que indica si el archivo se puede descargar en varios fragmentos o no. Si no se admite la fragmentación, configure BlockLength en el tamaño del archivo.

Intentar descargar un fragmento parcial cuando IsChunkingSupported está establecido en falso dará como resultado este error:

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

Usar mensajes de Dataverse para descargar un archivo

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

Publicación 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 usando el mensaje DownloadBlock.
DownloadBlock Solicite el tamaño del bloque, el valor de desplazamiento y el token de continuación del archivo.

Una vez que haya descargado todos los bloques, debe unirlos para crear el archivo descargado completo.

Puede usar una función como la siguiente para descargar un archivo o imagen usando el SDK mediante 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.

Encabezado 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 deben estar disponibles para los scripts que se ejecutan en el navegador, en respuesta a una solicitud de origen cruzado.
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. >

Descargar el archivo en fragmentos utilizando la API web

Nota

El siguiente ejemplo es para casos en los que IsChunkingSupported se establece en verdadero. Si es falso, utilice Descargar un archivo en una sola solicitud utilizando la API web.

Para descargar su archivo en fragmentos usando 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 a devolver usando este formato:
<unit>=<range-start>-<range-end>
Donde unit es bytes y range-start para la primera solicitud es 0.

No sabrá cuántas iteraciones se requieren para descargar el archivo completo hasta que obtenga la primera respuesta donde el encabezado de respuesta x-ms-file-size le 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 encabezado x-ms-file-size, 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 de origen cruzado.
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

Hay dos formas diferentes de eliminar archivos en una columna de archivos:

  • Usar los mensajes de Dataverse DeleteFile disponibles tanto para el SDK Webcomo para la API web
  • Enviar una solicitud DELETE utilizando la API web a la columna de archivo del registro.

Usar el mensaje DeleteFile

Utilizando el identificador único devuelto por CommitFileBlocksUploadResponse.FileId o recuperado de la columna como se describe en Comportamiento al recuperar, puede eliminar el archivo usando el mensaje DeleteFile.

Puede usar una función como la siguiente para eliminar un archivo usando el identificador único mediante la Clase DeleteFileRequest.

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

Enviar solicitud DELETE a la columna del archivo

Con la API web, puede eliminar un archivo enviando una solicitud DELETE a la ubicación del recurso de archivo.

El siguiente ejemplo elimina datos de un archivo para una columna llamadda 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 archivo
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 usando la API web de Dataverse

Nota

¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)

La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).