One of the things that has changed when you are building V2 extensions for a cloud environment is that you cannot access most functions that work with physical files.
This presents a bit of a challenge when it comes to working with the media and media set field types, as the typical approach is to have an import and export function so that a user can get pictures in and out of the field.
An example of this is the Customer Picture fact box that’s on the Customer Card:
As you can see, the import and export functions in C/Side leverage the FileManagement codeunit in order to transfer the picture image to and from a physical picture file. These functions are now blocked.
So…..we have got to take another approach. Enter streams.
Using the in and out stream types we can recreate the import and export functions without using any of the file based functions.
An import function would look like the following. In this example, the Picture field is defined as a Media Set field.
local procedure ImportPicture(); var PicInStream: InStream; FromFileName: Text; OverrideImageQst: Label 'The existing picture will be replaced. Do you want to continue?', Locked = false, MaxLength = 250; begin if Picture.Count > 0 then if not Confirm(OverrideImageQst) then exit; if UploadIntoStream('Import', '', 'All Files (*.*)|*.*', FromFileName, PicInStream) then begin Clear(Picture); Picture.ImportStream(PicInStream, FromFileName); Modify(true); end; end;
The UploadIntoStream function will prompt the user to choose a local picture file, and from there we upload that into an instream. At no point do we ever put the physical file on the server. Also note that the above example will always override any existing picture. You do not have to do this as media sets allow for multiple pictures. I’m just recreating the original example taken from the Customer Picture page.
For the export we have to write a bit more code. When using a Media Set field, we do not have access to any system function that allows us to export to a stream. To deal with this all we need to do is loop through the media set and get each of the corresponding media records. Once we have that then we can export each of those to a stream.
That would look like this:
local procedure ExportPicture(); var PicInStream: InStream; Index: Integer; TenantMedia: Record "Tenant Media"; FileName: Text; begin if Picture.Count = 0 then exit; for Index := 1 to Picture.Count do begin if TenantMedia.Get(Picture.Item(Index)) then begin TenantMedia.calcfields(Content); if TenantMedia.Content.HasValue then begin FileName := TableCaption + '_Image' + format(Index) + GetTenantMediaFileExtension(TenantMedia); TenantMedia.Content.CreateInStream(PicInstream); DownloadFromStream(PicInstream, '', '', '', FileName); end; end; end; end;
We use the DownloadFromStream function to prompt the user to save each of the pictures in the media set. As in our first example, there are no physical files ever created on the server, so we’re cloud friendly!
You may notice that I use the function GetTenantMediaFileExtension in the export example to populate the extension of the picture file. Since the user can upload a variety of picture file types, we need to make sure we create the file using the correct format.
The function to do this is quite simple, however there is no current function in the product to handle it, so you’ll have to build this yourself for now. Hopefully in the near future this function will be added by Microsoft.
local procedure GetTenantMediaFileExtension(var TenantMedia: Record "Tenant Media"): Text; begin case TenantMedia."Mime Type" of 'image/jpeg' : exit('.jpg'); 'image/png' : exit('.png'); 'image/bmp' : exit('.bmp'); 'image/gif' : exit('.gif'); 'image/tiff' : exit('.tiff'); 'image/wmf' : exit('.wmf'); end; end;
Until next time, happy coding!