I'm trying to upload a PDF file to a CRM record. I've used a File type field in the entity that can hold my uploaded file. I've done this by using this code:
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);
It is working fine for PDF files that are under 4 MB. However, If I try to upload a PDF that's more than 4 MB, I get the following error:
Invalid file chunk size: 4 MB. Maximum chunk size supported: 4 MB.
Is there a way to upload large PDF files to CRM record?
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);
}
CodePudding user response:
The UploadBlockRequest is one piece in the file upload procedure. You need 3 distinct requests:
InitializeFileBlocksUploadRequest
UploadBlockRequest
CommitFileBlocksUploadRequest
The UploadBlockRequest
can hold a chunk of 4 MB of data at a maximum. Your file can be as large as 128 MB and it can be uploaded using multiple upload requests.
A basic upload method could look like this:
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;
}
The method uploads the file and returns the ID of the file.
CodePudding user response:
I modified the example from Henk a little because I was having the error:
Buffer cannot be null
However, I believe my approach won't work for big files. I have tested this approach for files up to 5MB sucessfully. Files bigger than that will need to be uploaded using the approach from Henk. I'm not a coding genius myself to figure out the way Henk's example can be improved to avoid the bug.
private Guid UploadFile(byte[] fileBytes, string fileName, string mimeType, EntityReference target, string fileAttributeName, IOrganizationService ctx)
{
var initializeUploadRequest = new InitializeFileBlocksUploadRequest
{
FileAttributeName = fileAttributeName,
FileName = fileName,
Target = target
};
var initializeUploadResponse = (InitializeFileBlocksUploadResponse)ctx.Execute(initializeUploadRequest);
var uploadRequest = new UploadBlockRequest
{
FileContinuationToken = initializeUploadResponse.FileContinuationToken,
BlockData = fileBytes,
BlockId = Convert.ToBase64String(Guid.NewGuid().ToByteArray())
};
var blockList = new List<string>();
ctx.Execute(uploadRequest);
blockList.Add(uploadRequest.BlockId);
var commitRequest = new CommitFileBlocksUploadRequest
{
BlockList = blockList.ToArray(),
FileContinuationToken = initializeUploadResponse.FileContinuationToken,
FileName = initializeUploadRequest.FileName,
MimeType = mimeType
};
var commitResponse = (CommitFileBlocksUploadResponse)ctx.Execute(commitRequest);
return commitResponse.FileId;
}
}
I do work with a Byte Array as the input instead of a stream, as in my Solution I'm downloading a file from 1 entity (which is returned as a byte[]), to upload it in another entity.