添付ファイルとメモ レコードでファイル データを使用する

添付ファイル (ActivityMimeAttachment) および メモ (注釈) テーブルには、ファイル データを格納する特別な文字列列が含まれます。 これらのテーブルはファイルまたはイメージ列の前に存在するため、それらのテーブルとは動作が異なります。

  • バイナリ ファイル データは、Base64 でエンコードされた文字列値として文字列の列に格納されます。 添付ファイルは ActivityMimeAttachment.Body 列に格納され、メモは Annotation.DocumentBody 列に格納されます。
  • ファイル名データは FileName 列に格納されます。
  • MIME タイプのデータは、MimeType 列に格納されます。

FileNameMimeTypeActivityMimeAttachment.BodyAnnotation.DocumentBody は添付ファイルまたはメモ レコードのデータの一部であるため、これら 3 つの列を他の値と共に更新する必要があります。

activitymimeattachment.body 列と annotation.documentbody 列の値を、Base64 でエンコードされた文字列として直接取得および設定できます。 ファイルが大きすぎない限り、たとえば 4 MB 未満であれば、これらの値を設定しても問題ありません。 既定では、最大サイズは 5 MB です。 これらの列を構成して、最大 128 MB のファイルを受け入れることができます。 最大ファイル サイズを増やし、より大きなファイルを操作する場合は、提供されたメッセージを使用して、ファイルをアップロードまたはダウンロードするときにファイルを小さなチャンクに分割する必要があります。 ファイル サイズの制限を取得または変更する方法については、ファイル サイズの制限 を参照してください。

添付ファイル

添付ファイルは、電子メール活動に直接または電子メール テンプレート (テンプレート) を通じて関連付けられたファイルです。 複数の添付ファイルをアクティビティまたはテンプレートに関連付けることができます。 添付ファイルを再利用するには、bodyfilenamemimetype プロパティを設定するのではなく、activitymimeattachment.attachmentid 値を設定して別の既存の添付ファイルを参照します。

添付ファイルという名前の他の Dataverse テーブル

添付ファイル (ActivityMimeAttachment) を、Post テーブルに関連付けられたファイルをサポートする activityfileattachment と混合しないでください。

Dataverse スキーマ内には、Attachment という名前のパブリック テーブルもあり、Web API では添付 EntityType として公開されます。 このテーブルは照会可能で、 ActivityMimeAttachment テーブルのデータを反映します。 しかし、これは操作の作成、取得、更新、または削除はサポートしません。 このテーブルは、Power Apps デザイナー内には表示されません。

添付ファイルをアップロードする

InitializeAttachmentBlocksUploadUploadBlock、および CommitAttachmentBlocksUpload メッセージを使用して、添付ファイル用の大きなファイルをアップロードします。

重要

これらのメッセージは、新しい添付ファイルを作成する場合にのみ使用できます。 これらを使用して既存の添付ファイルを更新しようとすると、レコードが既に存在するというエラーが表示されます。

次の静的 UploadAttachment メソッドは、InitializeAttachmentBlocksUploadRequestUploadBlockRequest、および CommitAttachmentBlocksUploadRequest クラスを使用して添付ファイルを作成し、ActivityMimeAttachmentId および FileSizeInBytes プロパティを持つ CommitAttachmentBlocksUploadResponse を返す方法を示しています。

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

}

詳細情報:

注意

この関数には、ファイルの MIME タイプが提供されない場合に、FileExtensionContentTypeProvider.TryGetContentType(String, String) メソッドを使用してその MIME タイプを取得するロジックが含まれています。 種類が見つからない場合、application/octet-stream に設定されます。

添付ファイルのダウンロード

添付ファイルは、Web API を使用して一度の操作でダウンロードすることも、SDK または Web API を使用してチャンクでダウンロードすることもできます。

Web API を使用して添付ファイルを一度の操作でダウンロードする

Web API を使用して、一度の操作で添付ファイルをダウンロードできます。

ファイル列の取得とは異なり、このメソッドではファイル サイズ、ファイル名、または MIME タイプに関する情報は提供されません。

要求:

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

応答:

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

<Base64 string content removed for brevity>

詳細情報:

チャンクで添付ファイルをダウンロードする

ファイルをチャンクで取得するには、SDK または Web API で次のメッセージを使用します。

Message Description
InitializeAttachmentBlocksDownload ファイルのダウンロード元となるメモ レコードを指定します。 これは、バイト単位のファイル サイズと、DownloadBlock メッセージを使ってブロック単位でファイルをダウンロードする際に使用するファイル継続トークンを返します。
DownloadBlock ブロックのサイズ、オフセット値、ファイル継続トークンを要求します。

すべてのブロックをダウンロードしたら、それらを結合して、ダウンロードされたファイル全体を作成します。

次の静的 DownloadAttachment メソッドは、InitializeAttachmentBlocksDownloadRequestDownloadBlockRequest クラスを使用してファイルを含む新しい添付ファイルを作成し、SDK を使用して添付ファイルをダウンロードする方法について示しています。 この関数は byte[] データとファイル名を返します。

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

詳細情報:

注釈ファイル

メモは、テキストを含むテーブル行に関連付けられたレコードであり、単一のファイルが添付されている場合があります。 EntityMetadata.HasNotes が true に設定されているテーブルのみが、メモを関連付けることができます。

注釈ファイルをアップロードする

InitializeAnnotationBlocksUploadUploadBlock、および CommitAnnotationBlocksUpload メッセージを使用して、メモ用のファイルをアップロードします。

これらのメッセージの Target パラメータとして渡す注釈は、annotationid 値を持つ必要があります。 これは、既存の注釈レコードを更新する方法です。

通常、新しいレコードを作成するときに Dataverse に一意識別子の値を生成させるのが最善ですが、これらのメッセージでは不可能です。 これらのメッセージで新しい注釈を作成するには、Dataverse にこの値を生成するのではなく、新しい Guid 値を生成して annotationid 値として設定する必要があります。

次の静的 UploadNote メソッドでは、InitializeAnnotationBlocksUploadRequestUploadBlockRequest、および CommitAnnotationBlocksUploadRequest クラスを使用してファイルでメモを作成または更新する方法を説明します。 AnnotationId および FileSizeInBytes プロパティを持つ CommitAnnotationBlocksUploadResponse を返します。

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

詳細情報:

注意

この関数には、ファイルの MIME タイプが提供されない場合に、FileExtensionContentTypeProvider.TryGetContentType(String, String) メソッドを使用してその MIME タイプを取得するロジックが含まれています。 種類が見つからない場合、application/octet-stream に設定されます。

注釈ファイルをダウンロードする

メモ ファイルは、Web API を使用して一度の操作でダウンロードすることも、SDK または Web API を使用してチャンクでダウンロードすることもできます。

Web API を使用して注釈ファイルを一度の操作でダウンロードする

Web API を使用して、一度の操作でメモ ファイルをダウンロードできます:

ファイル列の取得とは異なり、このメソッドではファイル サイズ、ファイル名、または MIME タイプに関する情報は提供されません。

要求:

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

応答:

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

<Base64 string content removed for brevity>

詳細情報:

チャンクで注釈ファイルをダウンロードする

ファイルをチャンクで取得するには、SDK または Web API で次のメッセージを使用します。

Message Description
InitializeAnnotationBlocksDownload ファイルのダウンロード元となるメモ レコードを指定します。 これは、バイト単位のファイル サイズと、DownloadBlock メッセージを使ってブロック単位でファイルをダウンロードする際に使用するファイル継続トークンを返します。
DownloadBlock ブロックのサイズ、オフセット値、ファイル継続トークンを要求します。

すべてのブロックをダウンロードしたら、それらを結合して、ダウンロードされたファイル全体を作成します。

次の静的 DownloadNote メソッドは、InitializeAnnotationBlocksDownloadRequest および DownloadBlockRequest クラスを持つ SDK を使用してメモをダウンロードする方法を説明します。 この関数は byte[] データとファイル名を返します。

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

詳細情報:

ファイル サイズの制限

Organization.MaxUploadFileSize 列では、添付ファイルとメモ、およびそれ以外の種類のデータ (モデル駆動型アプリの Web リソース ファイルなど) のファイルの最大許容サイズをバイト単位で指定します。 アップロード ファイルの最大サイズの上限は、Base64 エンコーディングのファイル サイズに適用されます。 Base64 エンコーディングでは、元の byte[] ファイル データよりも大きな文字列が生成されます。

デフォルトのサイズは 5 MB (5242880バイト) で、最大値は 128 MB (131072000バイト) で、環境の電子メール設定で設定できます。 詳細: 機能設定の管理

大きすぎるファイルをアップロードしようとすると、次のエラーが発生します:

名前: unManagedidsattachmentinvalidfilesize
コード: 0x80044a02
番号: -2147202558
メッセージ: Attachment file size is too big.

最大アップロード ファイル サイズの取得

アップロード ファイルの最大サイズは、いくつかの方法で取得できます。

次の GetMaxUploadFileSize のような静的メソッドを使用して、値を取得します。

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

詳細情報:

最大アップロード ファイル サイズを変更する

organization.maxuploadfilesize 値はいくつかの方法で設定できます。

次の SetMaxUploadFileSize のような静的メソッドを使用して、アップロード ファイルの最大サイズを設定します。

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

詳細情報:

参照

ファイルおよび画像の概要
サンプル: .NET 用 Dataverse SDK を使用した添付ファイルとメモのファイル操作
サンプル: Dataverse Web API を使用した添付ファイルと注釈ファイルの操作

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。