Dynamics 365 Business Central: Conversion between Blob data type and Media/MediaSet data type

Dynamics 365 Business Central

Hi, Readers.
Today I would like to talk about how to convert between Blob data type and Media/MediaSet data type in AL.
As you might know, there are two ways that you can upload media in Business Central:

  • Use a BLOB data typeYou add media to a BLOB data type field on the record. For more information, see BLOB Data Type. (This is the only way to do it before the Media data type is released)

For example, Picture in Company Information:

table 79 “Company Information”:

  • Use a Media or MediaSet data type: This way enables you to store media in system tables of the database, and then reference the media from application records. For example, you can:
    • Display media with records in list type pages, when the page is viewed in the Tile layout. For more information, see Displaying Data as Tiles.
    • Display media on a card type page for a record.
    • Display media in a report.

Item Picture: MediaSet Data Type

Customer Picture: Media Data Type

PS: Using the Media or MediaSet data type provides better performance than using a BLOB data type and is more flexible in its design. With a BLOB data type, each time the media is rendered in the client, it’s retrieved from the SQL database server, which requires extra bandwidth and affects performance. With the Media and MediaSet data types, the client uses media ID to cache the media data, which in turn improves the response time for rendering the media in the user interface. More details: Working With Media on Records

So I have seen some upgrade cases consider converting the original Blob data type to Media/MediaSet data type. In this post, I will give you a few examples, I hope it will be helpful to you.

First, let’s look at the conversion between Blob data type and MediaSet data type. This time, take pictures (Bitmap) as an example. I added a new Blob data type field to the Item table and displayed it on the Item Card page.

This also saves an image of the item.

Since pictures of Blob data type don’t come with a delete function, I added one.
More details: Dynamics 365 Business Central: How to delete company logo (Picture in Company information)?

Test video:

Then add two actions. The first one is to copy the pciture of Blob data type to standard MediaSet data type.

Key steps:
Blob.CreateInStream(InStream [, TextEncoding]) Method: Creates an InStream object for a binary large object (BLOB). This enables you to read data from the BLOB.
MediaSet.ImportStream(InStream, Text [, Text]) Method: Adds a media file, such as a JPEG image, from an InStream object to the MediaSet of record for displaying in the client. The media is imported to the database and included in a MediaSet for the record.

Test:

Great.

The other is to copy the picture from the standard MediaSet data type to the Blob data type.

Key steps:
Blob.CreateInStream(InStream [, TextEncoding]) Method (Origin): Creates an InStream object for a binary large object (BLOB). This enables you to read data from the BLOB.
Blob.CreateOutStream(OutStream [, TextEncoding]) Method (Destination): Creates an OutStream object for a binary large object (BLOB). This enables you to write data to the BLOB.
System.CopyStream(OutStream, InStream [, Integer]) Method: Copies the information that is contained in an InStream to an OutStream.

Test:

Good.

Test video:

Source code: Github (Please note that the source code is for reference only, you can improve it according to your own needs)

tableextension 50200 ZYItemExt extends Item
{
    fields
    {
        field(50100; "Blob Picture"; BLOB)
        {
            Caption = 'Blob Picture';
            SubType = Bitmap;
        }
    }
}

pageextension 50200 ZYItemCardExt extends "Item Card"
{
    layout
    {
        addafter(Type)
        {
            field("ZY Picture"; Rec."Blob Picture")
            {
                ApplicationArea = All;
            }
        }
    }

    actions
    {
        addbefore(CopyItem)
        {
            action(ResetZYPicture)
            {
                ApplicationArea = All;
                Caption = 'Reset ZY Picture';
                Image = Delete;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                begin
                    if Rec."Blob Picture".HasValue then begin
                        Clear(Rec."Blob Picture");
                        CurrPage.SaveRecord();
                    end;
                end;
            }
            action(CopyBlobPictureToPicture)
            {
                ApplicationArea = All;
                Caption = 'Copy Blob Picture to Picture';
                Image = Import;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                var
                    InStr: InStream;
                    FileName: Text;
                begin
                    if Rec."Blob Picture".HasValue then begin
                        FileName := Rec."No." + '.png';
                        Rec."Blob Picture".CreateInStream(InStr);
                        Clear(Rec.Picture);
                        Rec.Picture.ImportStream(InStr, FileName);
                        Rec.Modify(true);
                    end;
                end;
            }
            action(CopyPictureToBlobPicture)
            {
                ApplicationArea = All;
                Caption = 'Copy Picture to Blob Picture';
                Image = Import;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                var
                    InStr: InStream;
                    OutStr: OutStream;
                    ItemTenantMedia: Record "Tenant Media";
                begin
                    if Rec.Picture.Count > 0 then begin
                        ItemTenantMedia.Get(Rec.Picture.Item(1));
                        ItemTenantMedia.CalcFields(Content);
                        ItemTenantMedia.Content.CreateInStream(InStr);
                        Rec."Blob Picture".CreateOutStream(OutStr);
                        CopyStream(OutStr, InStr);
                        Rec.Modify(true);
                    end;
                end;
            }
        }
    }
}

Media data type is similar to the above, I am briefly sharing the test results and code. In the same way, add a Blob data type field to the Customer table and then convert it.

Source code: Github (Please note that the source code is for reference only, you can improve it according to your own needs)

tableextension 50201 ZYCustomerExt extends Customer
{
    fields
    {
        field(50100; "Blob Picture"; BLOB)
        {
            Caption = 'Blob Picture';
            SubType = Bitmap;
        }
    }
}

pageextension 50201 ZYCustomerCardExt extends "Customer Card"
{
    layout
    {
        addafter(Blocked)
        {
            field("ZY Picture"; Rec."Blob Picture")
            {
                ApplicationArea = All;
            }
        }
    }

    actions
    {
        addbefore(Contact)
        {
            action(ResetZYPicture)
            {
                ApplicationArea = All;
                Caption = 'Reset ZY Picture';
                Image = Delete;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                begin
                    if Rec."Blob Picture".HasValue then begin
                        Clear(Rec."Blob Picture");
                        CurrPage.SaveRecord();
                    end;
                end;
            }
            action(CopyBlobPictureToPicture)
            {
                ApplicationArea = All;
                Caption = 'Copy Blob Picture to Picture';
                Image = Import;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                var
                    InStr: InStream;
                    FileName: Text;
                begin
                    if Rec."Blob Picture".HasValue then begin
                        FileName := Rec."No." + '.png';
                        Rec."Blob Picture".CreateInStream(InStr);
                        Clear(Rec.Image);
                        Rec.Image.ImportStream(InStr, FileName);
                        Rec.Modify(true);
                    end;
                end;
            }
            action(CopyPictureToBlobPicture)
            {
                ApplicationArea = All;
                Caption = 'Copy Picture to Blob Picture';
                Image = Import;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                var
                    InStr: InStream;
                    OutStr: OutStream;
                    CustTenantMedia: Record "Tenant Media";
                begin
                    if Rec.Image.HasValue then begin
                        CustTenantMedia.Get(Rec.Image.MediaId);
                        CustTenantMedia.CalcFields(Content);
                        CustTenantMedia.Content.CreateInStream(InStr);
                        Rec."Blob Picture".CreateOutStream(OutStr);
                        CopyStream(OutStr, InStr);
                        Rec.Modify(true);
                    end;
                end;
            }
        }
    }
}

Let’s look at another example, is it possible to transfer a file to Document Attachment?

Yes, of course, it is not that difficult. But you need to pay attention to the suffix of the conversion file.
Test video:

Source code: Github (Please note that the source code is for reference only, you can improve it according to your own needs)

tableextension 50202 ZYSalesHeaderExt extends "Sales Header"
{
    fields
    {
        field(50100; "Blob Picture"; BLOB)
        {
            Caption = 'Blob Picture';
            SubType = Bitmap;
        }
    }
}

pageextension 50202 ZYSalesOrderExt extends "Sales Order"
{
    layout
    {
        addafter("External Document No.")
        {
            field("ZY Picture"; Rec."Blob Picture")
            {
                ApplicationArea = All;
            }
        }
    }

    actions
    {
        addbefore(Post)
        {
            action(ResetZYPicture)
            {
                ApplicationArea = All;
                Caption = 'Reset ZY Picture';
                Image = Delete;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                begin
                    if Rec."Blob Picture".HasValue then begin
                        Clear(Rec."Blob Picture");
                        CurrPage.SaveRecord();
                    end;
                end;
            }
            action(CopyBlobPictureToAttachment)
            {
                ApplicationArea = All;
                Caption = 'Copy Blob Picture to Attachment';
                Image = Import;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;

                trigger OnAction()
                var
                    InStr: InStream;

                    FileName: Text;
                    DocAttach: Record "Document Attachment";
                begin
                    if Rec."Blob Picture".HasValue then begin
                        FileName := Rec."No." + ' ' + Rec."Sell-to Customer Name";
                        Rec."Blob Picture".CreateInStream(InStr);
                        DocAttach.Init();
                        DocAttach.Validate("Table ID", Database::"Sales Header");
                        DocAttach.Validate("Document Type", Enum::"Sales Document Type"::Order);
                        DocAttach.Validate("No.", Rec."No.");
                        DocAttach.Validate("File Name", FileName);
                        DocAttach.Validate("File Extension", 'png');
                        DocAttach."Document Reference ID".ImportStream(InStr, FileName);
                        DocAttach.Insert(true);
                    end;
                end;
            }
        }
    }
}

Very simple, give it a try!!!😁

PS:
1. Why is the Item picture uploaded to Business Central not as clear as the local one (looks blurry)? Is there any way out of this?

2. Dynamics 365 Business Central: How to export Work Description (Blob) in Sales Documents to excel

3. Dynamics 365 Business Central: How to add Media or MediaSet data type (Pictures) to a report

4. Dynamics 365 Business Central: How to copy Item Picture from one company to another – Customization

5. Dynamics 365 Business Central: How to show/display picture thumbnails on the list page

6. Dynamics 365 Business Central: How to convert Image (item picture) to encoded text (Base64 String) via AL

7. Dynamics 365 Business Central: How to import/create item picture from encoded text (Base64 String)

8. Dynamics 365 Business Central: How to add a picture to Item Category (Manage item picture by group) – Customization

9. Dynamics 365 Business Central: How to add and display multiple pictures for Item (Picture Gallery) – Customization

END

Hope this will help.

Thanks for reading.

ZHU

コメント

Copied title and URL