Partage via


Utiliser des données de fichier avec des enregistrements de pièce jointe et de note

Les tables Attachment (ActivityMimeAttachment) et Note (Annotation) contiennent des colonnes de chaîne spéciales qui stockent les données de fichier. Ces tables existaient avant les colonnes de fichiers ou d’images, elles fonctionnent donc différemment de ces tables.

  • Les données du fichier binaire sont stockées sous forme de valeurs de chaîne codées en Base64 dans des colonnes de chaîne. Les pièces jointes sont stockées dans la colonneActivityMimeAttachment.Body et les notes sont stockées dans la colonne Annotation.DocumentBody.
  • Les données de nom de fichier sont stockées dans la colonne FileName.
  • Les données de type MIME sont stockées dans la colonne MimeType.

Étant donné que FileName, MimeType, ActivityMimeAttachment.Body et Annotation.DocumentBody font partie des données de l’enregistrement de pièce jointe ou de note, vous devez mettre à jour ces trois colonnes avec toutes les autres valeurs.

Vous pouvez obtenir et définir directement les valeurs des colonnes activitymimeattachment.body et annotation.documentbody en tant que chaînes encodées en Base64. La définition de ces valeurs devrait convenir tant que les fichiers ne sont pas trop volumineux, par exemple moins de 4 Mo. Par défaut, la taille maximale est de 5 Mo. Vous pouvez configurer ces colonnes pour accepter des fichiers allant jusqu’à 128 Mo. Lorsque vous avez augmenté la taille de fichier maximale et que vous travaillez avec des fichiers plus volumineux, vous devez utiliser les messages fournis pour diviser les fichiers en plus petits morceaux lors du chargement ou du téléchargement de fichiers. Pour plus d’informations sur la récupération ou la modification des limites de taille de fichier, consultez Limites de taille de fichier.

Fichiers de pièce jointe

Une pièce jointe est un fichier associé à une activité e-mail , directement ou via un modèle d’e-mail (modèle). Plusieurs pièces jointes peuvent être associées à l’activité ou au modèle. Vous pouvez réutiliser les fichiers joints en définissant la valeur activitymimeattachment.attachmentid pour faire référence à une autre pièce jointe existante plutôt qu’en définissant les propriétés body, filename et mimetype.

Autres tables Dataverse nommées pièce jointe

La pièce jointe (ActivityMimeAttachment) ne doit pas être confondue avec activityfileattachment, qui prend en charge les fichiers associés à la table Post.

Dans le schéma Dataverse, il existe également une table publique portant le nom Attachment, qui est exposée dans l’API Web en tant que attachment EntityType. Cette table peut être interrogée et reflète les données de la table ActivityMimeAttachment. Mais elle ne prend pas en charge les opérations de création, de récupération, de mise à jour ou de suppression. Cette table n’apparaît pas dans le concepteur Power Apps.

Charger des fichiers de pièce jointe

Utilisez les messages InitializeAttachmentBlocksUpload, UploadBlock et CommitAttachmentBlocksUpload pour charger des fichiers volumineux pour les pièces jointes.

Important

Vous ne pouvez utiliser ces messages que pour créer une nouvelle pièce jointe. Si vous essayez de les utiliser pour mettre à jour une pièce jointe existante, vous obtiendrez une erreur indiquant que l’enregistrement existe déjà.

La méthode UploadAttachment statique suivante montre comment créer une pièce jointe avec un fichier à l’aide des classes InitializeAttachmentBlocksUploadRequest, UploadBlockRequest et CommitAttachmentBlocksUploadRequest pour renvoyer une CommitAttachmentBlocksUploadResponse avec les propriétés ActivityMimeAttachmentId et FileSizeInBytes.

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

}

Pour plus d’informations :

Notes

Cet exemple de méthode comprend une certaine logique pour essayer d’obtenir le Type MIME du fichier en utilisant la méthode FileExtensionContentTypeProvider.TryGetContentType(String, String), s’il n’est pas fourni. Si le type est introuvable, il est défini sur application/octet-stream.

Télécharger des fichiers de pièce jointe

Vous pouvez télécharger une pièce jointe en une seule opération à l’aide de l’API Web ou par tranches à l’aide du SDK ou de l’API Web.

Télécharger les fichiers joints en une seule opération à l’aide de l’API Web

Avec l’API web, vous pouvez télécharger des fichiers de pièce jointe en une seule opération.

Contrairement à la récupération des colonnes de fichier, cette méthode ne fournit pas d’informations sur la taille du fichier, le nom du fichier ou le type MIME.

Demande :

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

Réponse :

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

<Base64 string content removed for brevity>

Pour plus d’informations :

Télécharger des fichiers de pièce jointe par morceaux

Pour récupérer le fichier en morceaux, utilisez les messages suivants avec le SDK ou l’API Web :

Message Description
InitializeAttachmentBlocksDownload Spécifie l’enregistrement de note à partir duquel vous souhaitez télécharger un fichier. Il renvoie le taille de fichier en octets et un jeton de continuation de fichier que vous pouvez utiliser pour télécharger le fichier en blocs en utilisant le message DownloadBlock.
DownloadBlock Demande la taille du bloc, la valeur de décalage et le jeton de continuation de fichier.

Après avoir téléchargé tous les blocs, joignez-les pour créer l’intégralité du fichier téléchargé.

La méthode statique DownloadAttachment suivante montre comment télécharger une pièce jointe à l’aide du SDK avec les classes InitializeAttachmentBlocksDownloadRequest et DownloadBlockRequest. Cette fonction renvoie les données byte[] et le nom du fichier.

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

Pour plus d’informations :

Fichiers de notes

Une note est un enregistrement associé à une ligne de table qui contient du texte et peut avoir un seul fichier joint. Seules les tables avec EntityMetadata.HasNotes défini sur true peuvent avoir des notes associées.

Charger des fichiers de notes

Utilisez les messages InitializeAnnotationBlocksUpload, UploadBlock et CommitAnnotationBlocksUpload pour charger des fichiers volumineux pour les notes.

La note que vous transmettez comme paramètre Target pour ces messages doit avoir une valeur annotationid. C’est ainsi que vous pouvez mettre à jour les enregistrements de notes existants.

Normalement, il est préférable de laisser Dataverse générer les valeurs d’identifiant uniques lors de la création de nouveaux enregistrements, mais cela n’est pas possible avec ces messages. Pour créer une note avec ces messages, vous devez générer une nouvelle valeur Guid à définir comme valeur annotationid plutôt que laisser Dataverse générer la valeur.

La méthode statique UploadNote suivante montre comment créer ou mettre à jour une note avec un fichier à l’aide des classes InitializeAnnotationBlocksUploadRequest, UploadBlockRequest et CommitAnnotationBlocksUploadRequest. Elle renvoie une CommitAnnotationBlocksUploadResponse avec les propriétés AnnotationId et FileSizeInBytes.

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

Pour plus d’informations :

Notes

Cet exemple de méthode comprend une certaine logique pour essayer d’obtenir le Type MIME du fichier en utilisant la méthode FileExtensionContentTypeProvider.TryGetContentType(String, String), s’il n’est pas fourni. Si le type est introuvable, il est défini sur application/octet-stream.

Télécharger des fichiers de notes

Vous pouvez télécharger un fichier de note en une seule opération à l’aide de l’API Web ou par tranches à l’aide du SDK ou de l’API Web.

Télécharger les fichiers d’annotation en une seule opération à l’aide de l’API Web

Avec l’API web, vous pouvez télécharger un fichier de note en une seule opération :

Contrairement à la récupération des colonnes de fichier, cette méthode ne fournit pas d’informations sur la taille du fichier, le nom du fichier ou le type MIME.

Demande :

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

Réponse :

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

<Base64 string content removed for brevity>

Pour plus d’informations :

Télécharger des fichiers d’annotation par morceaux

Pour récupérer le fichier en morceaux, utilisez les messages suivants avec le SDK ou l’API Web :

Message Description
InitializeAnnotationBlocksDownload Spécifie l’enregistrement de note à partir duquel vous souhaitez télécharger un fichier. Il renvoie le taille de fichier en octets et un jeton de continuation de fichier que vous pouvez utiliser pour télécharger le fichier en blocs en utilisant le message DownloadBlock.
DownloadBlock Demande la taille du bloc, la valeur de décalage et le jeton de continuation de fichier.

Après avoir téléchargé tous les blocs, joignez-les pour créer l’intégralité du fichier téléchargé.

La méthode statique DownloadNote suivante montre comment télécharger une note à l’aide du SDK avec les classes InitializeAnnotationBlocksDownloadRequest et DownloadBlockRequest. Cette fonction renvoie les données byte[] et le nom du fichier.

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

Pour plus d’informations :

Limites de taille de fichier

La colonne Organization.MaxUploadFileSize spécifie la taille maximale autorisée d’un fichier en octets pour une pièce jointe et une note, et d’autres types de données, telles que les fichiers de ressources Web utilisés pour le modèle. applications pilotées. La limite de taille maximale des fichiers de chargement s’applique à la taille du fichier avec l’encodage Base64. Un encodage Base64 produit une chaîne plus volumineuse que les données de fichier byte[] originales.

La taille par défaut est de 5 Mo (5 242 880 octets) et la valeur maximale est de 128 Mo (131 072 000 octets) et peut être définie dans les paramètres de messagerie de l’environnement. Pour plus d’informations : Gérer les paramètres de courrier électronique

Si vous essayez d’importer un fichier trop volumineux, vous obtenez l’erreur suivante :

Nom: unManagedidsattachmentinvalidfilesize
Code : 0x80044a02
Nombre : -2147202558
Message : Attachment file size is too big.

Récupérer la taille maximale du fichier à charger

Vous pouvez récupérer la taille maximale du fichier de téléchargement de plusieurs manières.

Utilisez une méthode statique comme la suivante GetMaxUploadFileSize pour obtenir la valeur.

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

Pour plus d’informations :

Modifier la taille maximale du fichier de chargement

Vous pouvez définir la valeur organization.maxuploadfilesize de plusieurs manières.

Utilisez une méthode statique comme la suivante SetMaxUploadFileSize pour définir la taille maximale du fichier à charger.

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

Pour plus d’informations :

Voir aussi

Vue d’ensemble des fichiers et des images
Exemple : opérations sur les fichiers avec des pièces jointes et des notes à l’aide du SDK Dataverse pour .NET
Exemple : opérations sur les fichiers de pièce jointe et de notes à l’aide de l’API web Dataverse

Notes

Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)

Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).