将 PDF ( > 4 MB) 上传到 D365 CRM 中的文件数据类型

Posted

技术标签:

【中文标题】将 PDF ( > 4 MB) 上传到 D365 CRM 中的文件数据类型【英文标题】:Upload PDF ( > 4 MB) to File datatype in D365 CRM 【发布时间】:2022-01-23 19:51:42 【问题描述】:

我正在尝试将 PDF 文件上传到 CRM 记录。我在实体中使用了一个文件类型字段来保存我上传的文件。我已经通过使用此代码完成了此操作:

UploadBlockRequest blockRequest = new UploadBlockRequest();
blockRequest.BlockData = Convert.FromBase64String(documentBody);
blockRequest.BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));
blockRequest.FileContinuationToken = initResponse.FileContinuationToken;

var blockResponse = (UploadBlockResponse)service.Execute(blockRequest);

它适用于小于 4 MB 的 PDF 文件。但是,如果我尝试上传超过 4 MB 的 PDF,则会收到以下错误:

文件块大小无效:4 MB。支持的最大块大小:4 MB。

有没有办法将大型 PDF 文件上传到 CRM 记录?

using (var stream = new MemoryStream(Convert.FromBase64String(Base64)))
                    
                        InitializeFileBlocksUploadRequest initializeUploadRequest = new InitializeFileBlocksUploadRequest();
                        initializeUploadRequest.FileAttributeName = "my_fileTypeField";
                        initializeUploadRequest.FileName = "Test.pdf";
                        initializeUploadRequest.Target = new EntityReference("my_entity", new Guid("my_guid"));

                        var initializeUploadResponse = (InitializeFileBlocksUploadResponse)service.Execute(initializeUploadRequest);
                        var uploadRequest = new UploadBlockRequest  FileContinuationToken = initializeUploadResponse.FileContinuationToken ;

                        const int blockSize = 4194304; // 4MB
                        int byteCount;
                        var blockList = new List<string>();

                        do
                        
                            
                            //uploadRequest.BlockData = Convert.FromBase64String(documentBody);
                            byteCount = stream.Read(uploadRequest.BlockData, 0, blockSize);
                            uploadRequest.BlockId = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
                            service.Execute(uploadRequest);
                            blockList.Add(uploadRequest.BlockId);
                            Console.WriteLine(size + " == " + blockSize);
                         while (size == blockSize);

                        var commitRequest = new CommitFileBlocksUploadRequest
                        
                            BlockList = blockList.ToArray(),
                            FileContinuationToken = initializeUploadResponse.FileContinuationToken,
                            FileName = initializeUploadRequest.FileName,
                            MimeType = "application/pdf"
                        ;
                        var commitResponse = (CommitFileBlocksUploadResponse)service.Execute(commitRequest);
                    

【问题讨论】:

我的回答解决了你的问题吗? 【参考方案1】:

UploadBlockRequest 是文件上传过程中的一部分。您需要 3 个不同的请求:

    InitializeFileBlocksUploadRequest UploadBlockRequest CommitFileBlocksUploadRequest

UploadBlockRequest 最多可以容纳 4 MB 的数据块。您的文件最大可达 128 MB,并且可以使用多个上传请求上传。

一个基本的上传方法可能如下所示:

private static Guid UploadFile
    (
        Stream stream,
        string fileName,
        string mimeType,
        EntityReference target,
        string fileAttributeName,
        IOrganizationService organizationService
    )

    var initializeUploadRequest = new InitializeFileBlocksUploadRequest
    
        FileAttributeName = fileAttributeName,
        FileName = fileName,
        Target = target
    ;

    var initializeUploadResponse = (InitializeFileBlocksUploadResponse)organizationService.Execute(initializeUploadRequest);

    const int blockSize = 4194304; // 4 MB
    int byteCount;
    var blockList = new List<string>();

    do
    
        var buffer = new byte[blockSize];
        byteCount = stream.Read(buffer, 0, blockSize);

        if (byteCount < blockSize)
            Array.Resize(ref buffer, byteCount);

        var uploadRequest = new UploadBlockRequest
        
            BlockData = buffer,
            BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N"))),
            FileContinuationToken = initializeUploadResponse.FileContinuationToken
        ;

        organizationService.Execute(uploadRequest);
        blockList.Add(uploadRequest.BlockId);
     while (byteCount == blockSize);

    var commitRequest = new CommitFileBlocksUploadRequest
    
        BlockList = blockList.ToArray(),
        FileContinuationToken = initializeUploadResponse.FileContinuationToken,
        FileName = initializeUploadRequest.FileName,
        MimeType = mimeType
    ;

    var commitResponse = (CommitFileBlocksUploadResponse)organizationService.Execute(commitRequest);
    return commitResponse.FileId;

该方法上传文件并返回文件的ID。

【讨论】:

感谢您的回答。我正在传递 base64 字符串而不是文件流。在那种情况下,我将如何比较 do-while 的条件? 从 base64 字符串创建一个 Stream,如下所示:using (var stream = new MemoryStream(Convert.FromBase64String(documentBody))) 并将流提供给方法。当然,您需要将FileStream 更改为MemoryStream,或者更简单地更改为基类Stream 嗨 Henk van Boeijen,在执行上述代码后,我得到以下异常:异常捕获 - 缓冲区不能为空。参数名称:缓冲区。我正在更新我的问题,以便您查看我的实现。 我遇到了和@3iL 一样的问题。 我为草率的代码示例道歉。应该先测试一下。我修复了它并更新了我的答案。

以上是关于将 PDF ( > 4 MB) 上传到 D365 CRM 中的文件数据类型的主要内容,如果未能解决你的问题,请参考以下文章

如何将 > 5 mb 的图像上传到服务器?

HTML 页面到 PDF(角度 js 和 d3 图表)

如何将大 (> 25MB) 文件上传到 Web 服务?

怎么将pdf文件压缩到指定大小?

如何使用 alamofire 将多个 PDF 文件上传到服务器? #Swift 4 #IOS [重复]

将 pdf 上传到 Cloudinary