13.2 Streams, File Management & TempBlob
Key Takeaways
- InStream and OutStream provide sequential byte-level data streaming in AL, reading from and writing to binary buffers, files, and network connections in memory chunks without loading entire payloads into RAM.
- The TempBlob codeunit in the System Application serves as the universal in-memory binary container, replacing the deprecated legacy TempBlob table.
- In Business Central SaaS (target = Cloud), direct access to the server filesystem using the File data type or .NET file I/O is strictly prohibited, requiring browser stream dialogs or cloud storage APIs.
- Interactive file transfer between the Web Client browser and the Business Central Server tier is managed via UploadIntoStream() and DownloadFromStream().
- Codeunit 4114 Base64 Convert provides high-performance bidirectional translation between binary streams and Base64-encoded strings for JSON and REST API payloads.
13.2 Streams, File Management & TempBlob
In modern cloud-first architectures for Microsoft Dynamics 365 Business Central, direct access to the server's local physical filesystem is strictly blocked. All document imports, exports, image processing, report rendering, and REST API payload transformations rely on Streams and memory-backed binary containers. For the MB-820 exam, developers must master InStream, OutStream, the TempBlob codeunit, cloud file transfer dialogs, and Base64 encoding routines.
1. AL Stream Architecture: InStream & OutStream Fundamentals
Streams represent sequential sequences of bytes. Rather than loading massive text files, PDFs, or binary payloads entirely into memory as strings (which can exceed string length limits and trigger Out-Of-Memory exceptions on the NST), streams process data continuously in buffered chunks.
local procedure DemonstrateStreamProcessing()
var
TempBlob: Codeunit "Temp Blob";
WriteOutStream: OutStream;
ReadInStream: InStream;
LineContent: Text;
RecordCount: Integer;
begin
// 1. Initialize OutStream and write structured data
TempBlob.CreateOutStream(WriteOutStream, TextEncoding::UTF8);
WriteOutStream.WriteText('ItemNo,Description,UnitPrice');
WriteOutStream.WriteText(); // Writes CRLF delimiter
WriteOutStream.WriteText('1001,Touring Bicycle,1250.00');
WriteOutStream.WriteText();
WriteOutStream.WriteText('1002,Mountain Bike,1450.00');
// 2. Initialize InStream and read sequentially line by line
TempBlob.CreateInStream(ReadInStream, TextEncoding::UTF8);
while not ReadInStream.EOS() do begin
ReadInStream.ReadText(LineContent);
RecordCount += 1;
// Process LineContent
end;
Message('Processed %1 lines from stream.', RecordCount);
end;
Stream Types and Core Methods
InStream(Input Stream): Used to read sequential binary or text data from a source (such as a database BLOB, file upload, or HTTP response):InStream.Read(Variant [, Length]): Reads raw binary bytes into a variable.InStream.ReadText(Text [, Length]): Reads a string of text up to the next newline delimiter or specified character length.InStream.EOS(): Returnstruewhen the End of Stream is reached.InStream.Position: Returns or sets the current byte offset within the stream.
OutStream(Output Stream): Used to write sequential binary or text data to a destination (such as a database BLOB, file download, or HTTP request content):OutStream.Write(Variant [, Length]): Writes raw binary data to the stream.OutStream.WriteText(Text): Appends text characters to the stream.OutStream.WriteText(): Writes standard newline characters (CRLF).
Text Encoding Options
When initializing streams, developers should explicitly define character encoding using the TextEncoding enum:
TextEncoding::UTF8(Default standard for JSON, REST APIs, XML, and modern web integrations).TextEncoding::UTF16(Wide-character Unicode).TextEncoding::Windows(ANSI Windows codepage, common in legacy file exports).TextEncoding::MSDos(Legacy OEM ASCII encoding).
2. The TempBlob Codeunit & In-Memory Binary Management
In legacy C/AL development, binary objects were stored and manipulated using temporary records on a system TempBlob table (Record "TempBlob" temporary). In modern AL, Microsoft deprecated the table approach in favor of the TempBlob Codeunit (Codeunit 4100 "Temp Blob" in the System Application).
local procedure StoreCustomerPicture(CustNo: Code[20]; var ImageInStream: InStream)
var
Customer: Record Customer;
TempBlob: Codeunit "Temp Blob";
BlobOutStream: OutStream;
BlobInStream: InStream;
begin
if not Customer.Get(CustNo) then
exit;
// Read from source InStream and write into TempBlob container
TempBlob.CreateOutStream(BlobOutStream);
CopyStream(BlobOutStream, ImageInStream);
// Verify binary payload presence and length
if TempBlob.HasValue() then begin
Message('Blob payload size: %1 bytes', TempBlob.Length());
// Import from TempBlob into Customer Media field
TempBlob.CreateInStream(BlobInStream);
Clear(Customer.Image);
Customer.Image.ImportStream(BlobInStream, 'Customer Picture', 'image/jpeg');
Customer.Modify(true);
end;
end;
TempBlob Codeunit Core API
CreateInStream(var InStream [, TextEncoding]): Creates anInStreamreader pointing to the beginning of the memory buffer.CreateOutStream(var OutStream [, TextEncoding]): Creates anOutStreamwriter, clearing any prior contents in the memory buffer.Length(): Returns the total size of the binary payload in bytes as anInteger.HasValue(): Returns aBooleanindicating whether the buffer contains one or more bytes (Length() > 0).CopyStream(OutStream, InStream): System function that transfers all bytes from anInStreamdirectly into anOutStreamin optimized memory chunks.
Handling Table BLOB & Media/MediaSet Fields
- BLOB Fields: Stored directly within table rows in SQL. To read or write, call
Record.BlobField.CreateInStream(InStream)orRecord.BlobField.CreateOutStream(OutStream). Media&MediaSetData Types: Modern alternatives to table BLOBs. Instead of storing large binary blobs inside the transactional business table,Mediastores images and attachments in a dedicated system table (Tenant Media), referencing them via a uniqueMediaId(GUID). This keeps business tables lightweight and optimizes database performance.
3. Cloud File Management: UploadIntoStream & DownloadFromStream
In Business Central SaaS environments ("target": "Cloud"), AL code cannot access local drives (C:\) or physical network shares. Attempting to use the native File data type or .NET file I/O triggers compilation errors. File interactions must be handled through client-side stream dialogs or cloud storage APIs.
local procedure ExportSalesLedgerCsv()
var
CustLedgEntry: Record "Cust. Ledger Entry";
TempBlob: Codeunit "Temp Blob";
ExportOutStream: OutStream;
ExportInStream: InStream;
ClientFileName: Text;
begin
// 1. Build CSV content into TempBlob OutStream
TempBlob.CreateOutStream(ExportOutStream, TextEncoding::UTF8);
ExportOutStream.WriteText('EntryNo,PostingDate,CustomerNo,Amount');
ExportOutStream.WriteText();
if CustLedgEntry.FindSet() then
repeat
ExportOutStream.WriteText(StrSubstNo('%1,%2,%3,%4',
CustLedgEntry."Entry No.",
CustLedgEntry."Posting Date",
CustLedgEntry."Customer No.",
CustLedgEntry.Amount));
ExportOutStream.WriteText();
until CustLedgEntry.Next() = 0;
// 2. Deliver the InStream to the user's web browser
TempBlob.CreateInStream(ExportInStream);
ClientFileName := 'CustomerLedgerExport.csv';
DownloadFromStream(ExportInStream, 'Download Export', '', 'CSV Files (*.csv)|*.csv', ClientFileName);
end;
local procedure ImportFileFromUser()
var
UploadInStream: InStream;
DialogTitle: Text;
FromFileName: Text;
begin
DialogTitle := 'Select XML Document to Import';
// Upload from client machine directly into an InStream
if UploadIntoStream(DialogTitle, '', 'XML Files (*.xml)|*.xml', FromFileName, UploadInStream) then begin
Message('Successfully uploaded file: %1', FromFileName);
// Parse UploadInStream with XmlDocument or XMLport
end;
end;
Core Client-Server File Transfer APIs
UploadIntoStream(DialogTitle, FromFolder, FromFilter, FromFile, InStream): Displays a file picker dialog in the web browser. The uploaded file content is streamed directly into the providedInStreamvariable.DownloadFromStream(InStream, DialogTitle, ToFolder, ToFilter, ToFile): Streams data from the Business Central Server to the user's web browser, triggering the browser's native file download workflow.Codeunit 419 "File Management": Contains high-level helper routines, such as extracting file extensions (GetExtension), resolving MIME types (GetMimeType), extracting file names (GetFileName), and converting files to temporary server paths when running in on-premises environments.
4. Base64 Encoding & REST API Payload Integration
Web services and RESTful APIs commonly transmit binary files (PDFs, images, spreadsheets) as Base64-encoded strings embedded within JSON or XML payloads. Business Central provides Codeunit 4114 "Base64 Convert" to perform bidirectional conversion.
local procedure BuildJsonPayloadWithPdfAttachment(var PdfInStream: InStream): Text
var
Base64Convert: Codeunit "Base64 Convert";
JsonObjectPayload: JsonObject;
Base64PdfString: Text;
SerializedJson: Text;
begin
// Convert binary InStream directly to Base64 Text
Base64PdfString := Base64Convert.ToBase64(PdfInStream);
// Embed into JSON Object
JsonObjectPayload.Add('documentType', 'Invoice');
JsonObjectPayload.Add('mimeType', 'application/pdf');
JsonObjectPayload.Add('payloadBase64', Base64PdfString);
JsonObjectPayload.WriteTo(SerializedJson);
exit(SerializedJson);
end;
local procedure DecodeBase64PayloadToTempBlob(Base64Content: Text; var TempBlob: Codeunit "Temp Blob")
var
Base64Convert: Codeunit "Base64 Convert";
TargetOutStream: OutStream;
begin
TempBlob.CreateOutStream(TargetOutStream);
// Decode Base64 string directly into the OutStream
Base64Convert.FromBase64(Base64Content, TargetOutStream);
end;
Base64 Convert Method Overloads
ToBase64(InStream): Reads bytes from anInStreamand returns a Base64-encodedTextstring.ToBase64(Text): Converts an unencoded string to its Base64 representation.FromBase64(Base64Text, OutStream): Decodes a Base64 string and streams the raw binary bytes directly into the targetOutStream.FromBase64(Base64Text): Decodes a Base64 string back into plainText.
A developer is migrating a legacy C/AL report to AL for a Business Central SaaS deployment. The legacy code contains: ServerFile.Create('C:\Exports\Output.txt'); ServerFile.Write(ExportData); ServerFile.Close();. How must this logic be refactored to comply with Cloud development requirements?
An AL procedure needs to read a binary image uploaded by a user and store it in an in-memory buffer to verify its byte length before saving. Which sequence of TempBlob operations correctly accomplishes this?
An AL integration routine receives a JSON object from an external logistics API containing a Base64-encoded packing slip PDF string in a property named 'pdfData'. Which codeunit and method should be used to convert this string into binary bytes for storage?
When reading structured lines from a text stream using InStream.ReadText(LineContent), how does the InStream determine when a single line ends, and how is the end of the entire stream detected?