Since the storage is pretty expensive in Business Central and you only get 80GB for all your Dev, Test and Live environments it doesn’t make much sense to store large files in Business Central.

Lets say we have a business requirement that every time we create a sales quote we need to take a picture with a mobile phone and save that picture somewhere where its related to the Sales Quote in Business Central.
Luckily its pretty easy to do with Business Central since most of the code is available from the System App to communicate with the Sharepoint Online and we as a Business Central Developer just need to put all those puzzle pieces together.

If you search for Sharepoint you will find many objects related to Sharepoint:

There is also quite nice blog that explains how to get Sharepoint working in AL: https://simplanova.com/blog/utilizing-the-system-applications-sharepoint-connector-module-to-manage-files-in-business-central/

Only thing that didn’t work for me very well from that blog was the scope.

I had to use /AllSites.FullControl scope for my Sharepoint site to get this fully functional.

When the base for Sharepoint connection is set up then you need two procedures to create folder and create files in Sharepoint.

    procedure UploadFileToSharepointFolder(FolderName: Text; FileName: Text; FileInstream: InStream): Boolean
    var
        Diagnostics: Interface "HTTP Diagnostics";
        ConnectionError: Label 'Error with sharepoint connection - %1';
        SharepointSetup: Record "SHP Sharepoint Connector Setup";
        SharepointFolder: Record "SharePoint Folder" temporary;
        SharepointFile: Record "SharePoint File" temporary;
        RelativeUrl: text;
        RootUrl: text;
    begin
        InitializeConnection();
        SharepointSetup.SetLoadFields("CRM Documents Root Folder Name");
        if SharepointSetup.Get() then begin
            SharepointSetup.TestField("CRM Documents Root Folder Name");
            RelativeUrl := '/' + 'Shared Documents' + '/' + SharepointSetup."CRM Documents Root Folder Name" + '/' + FolderName;

            if SharepointClient.AddFileToFolder(RelativeUrl, FileName, FileInstream, SharepointFile) then begin
                exit(true);
            end;

            Diagnostics := SharepointClient.GetDiagnostics();
            if (not Diagnostics.IsSuccessStatusCode()) then
                Error(ConnectionError, Diagnostics.GetErrorMessage() + ' | ' + Diagnostics.GetResponseReasonPhrase());

        end;
    end;

    procedure CreateFolder(FolderName: Text): Boolean
    var
        Diagnostics: Interface "HTTP Diagnostics";
        ConnectionError: Label 'Error with sharepoint connection - %1';
        SharepointSetup: Record "SHP Sharepoint Connector Setup";
        SharepointFolder: Record "SharePoint Folder" temporary;
        SharepointFile: Record "SharePoint File" temporary;
        RelativeUrl: text;
        RootUrl: text;
    begin
        InitializeConnection();
        SharepointSetup.SetLoadFields("CRM Documents Root Folder Name");
        if SharepointSetup.Get() then begin
            SharepointSetup.TestField("CRM Documents Root Folder Name");
            RelativeUrl := '/' + 'Shared Documents' + '/' + SharepointSetup."CRM Documents Root Folder Name" + '/' + FolderName;
            if SharepointClient.CreateFolder(RelativeUrl, SharepointFolder) then begin
                exit(true);
            end;

            Diagnostics := SharepointClient.GetDiagnostics();
            if (not Diagnostics.IsSuccessStatusCode()) then
                Error(ConnectionError, Diagnostics.GetErrorMessage() + ' | ' + Diagnostics.GetResponseReasonPhrase());

        end;
    end;

After these procedure I could create a action that opens camera on the device and I can take pictures.

pageextension 75560 "POS Sales Quote" extends "Sales Quote"
{
    layout
    {
        // Add changes to page layout here
    }

    actions
    {
        addlast(Promoted)
        {
            actionref(TakePicture; "POS TakePicture")
            {

            }
        }
        addlast("&Quote")
        {
            action("POS TakePicture")
            {
                Caption = 'Take Picture';
                ApplicationArea = All;
                Visible = true;
                Image = Camera;
                trigger OnAction()
                var
                    CameraInteraction: Page Camera;
                    PictureStream: InStream;
                    EncodingType: Enum "Image Encoding";
                    TembBlob: Codeunit "Temp Blob";
                    Base64Convert: Codeunit "Base64 Convert";
                    Base64Picture: Text;
                    SharepointConnector: Codeunit "SHP Sharepoint Integration";
                begin
                    if CameraInteraction.IsAvailable() then begin
                        CameraInteraction.SetAllowEdit(true);
                        CameraInteraction.SetQuality(50);
                        CameraInteraction.SetEncodingType(EncodingType::PNG);
                        CameraInteraction.RunModal();
                        CameraInteraction.GetPicture(TembBlob);
                        TembBlob.CreateInStream(PictureStream);
                        if SharepointConnector.CreateFolder(Rec."No.") then
                            if SharepointConnector.UploadFileToSharepointFolder(Rec."No.", 'IMG' + Format(Random(20000)) + '.png', PictureStream) then
                                Message('Picture Uploaded');
                    end else
                        Message('Camera is not available on this device.');
                end;
            }
        }
    }
}

Then I can take a picture from the Sales Quote and that picture will be saved to the Sharepoint and a link is attached to a Quote in Business Central:

And in Sharepoint I have all my dog pictures related to the Sales Quote in Business Central : )