Skip to main content

Anhang Download

Diese Dokumentation bietet umfassende Anleitung für externe AL-Entwickler zum Abrufen und Herunterladen einzelner Anhänge aus DXP Freeze für verknüpfte Business Central Datensätze.

Überblick

Die DXP Freeze Result Management Codeunit bietet Methoden zum direkten Zugriff auf einzelne Anhänge archivierter Datensätze:

  1. GetAttachments - Lädt Metadaten aller Anhänge eines Datensatzes
  2. GetSpecificRecordAttachment - Lädt den Inhalt eines spezifischen Anhangs als Base64
  3. Kombinierte Verwendung ermöglicht gezielte Filterung und Download einzelner Dateien

Diese Methoden ermöglichen präzise Kontrolle über welche Anhänge abgerufen werden und wie sie verarbeitet werden, ohne ZIP-Archive zu erstellen.


Methode 1: GetAttachments

Zweck

Ruft Metadaten aller Anhänge eines archivierten Datensatzes ab. Diese Methode füllt einen temporären DXP FRZ Attachment Result Record mit Informationen über verfügbare Anhänge ohne den eigentlichen Dateiinhalt herunterzuladen.

Verfügbare Überladungen

1. Standard-Verwendung

procedure GetAttachments(RecordHeaderID: Guid; RecordHeaderFileLink: Text[2048]; var TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary)

2. Mit Kontrolle über Datenlöschung

procedure GetAttachments(RecordHeaderID: Guid; RecordHeaderFileLink: Text[2048]; var TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary; ClearAttachmentTable: Boolean)

Parameter

Parameter Typ Beschreibung
RecordHeaderID Guid Eindeutige ID des Freeze-Datensatzes
RecordHeaderFileLink Text[2048] API-Link zum Datensatz (aus DXP FRZ Record Result Header."File Link")
TempFrzAttachmentResult Record (temporary, var) Temporärer Record, der mit Anhang-Metadaten gefüllt wird
ClearAttachmentTable Boolean true = Record vor Befüllung löschen; false = zu bestehenden Einträgen hinzufügen

Rückgabewert

Keine - Die Methode füllt den übergebenen temporären Record mit Anhang-Metadaten.

Anhang-Metadaten-Felder

Jeder Eintrag in TempFrzAttachmentResult enthält:

Feld Beschreibung
ID Eindeutige Anhang-ID (Guid)
Record Header Id Verknüpfung zum übergeordneten Datensatz
Filename Dateiname mit Erweiterung
File Extension Dateierweiterung (automatisch aus Filename extrahiert)
Filesize Größe in Bytes
Author Ersteller des Anhangs
Archived at Archivierungszeitpunkt
File Link API-Link zum Datensatz

Verwendungsbeispiel

procedure ListAttachmentsForSalesInvoice(SalesInvoiceNo: Code[20])
var
    SalesInvoiceHeader: Record "Sales Invoice Header";
    TempFrzResultQueryHeader: Record "DXP FRZ Query Result Header" temporary;
    TempFrzResultRecordHeader: Record "DXP FRZ Record Result Header" temporary;
    TempFrzResultRecordField: Record "DXP FRZ Result Record-Field" temporary;
    TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary;
    FrzSearchMgt: Codeunit "DXP Freeze Search Mgt.";
    FrzResultMgt: Codeunit "DXP FRZ Result Mgt.";
    FrzApiMgt: Codeunit "DXP Freeze API Mgt.";
    QueryResult: JsonObject;
    SearchQuery: Text;
begin
    if not SalesInvoiceHeader.Get(SalesInvoiceNo) then
        Error('Rechnung %1 nicht gefunden.', SalesInvoiceNo);

    // Suchanfrage für diesen Datensatz erstellen
    SearchQuery := FrzSearchMgt.GetSearchCombinationForTable(
        SalesInvoiceHeader.SystemId, 
        Database::"Sales Invoice Header"
    );

    // Freeze durchsuchen
    QueryResult := FrzApiMgt.SubmitSearch(SearchQuery);

    // Ergebnisse verarbeiten - dies füllt den Record Header
    FrzResultMgt.CreateResult(
        QueryResult,
        TempFrzResultQueryHeader,
        TempFrzResultRecordHeader,
        TempFrzResultRecordField,
        TempFrzAttachmentResult,
        SearchQuery
    );

    // Prüfen ob Datensatz gefunden wurde
    if TempFrzResultRecordHeader.FindFirst() then begin
        // Anhänge für diesen Record Header abrufen
        FrzResultMgt.GetAttachments(
            TempFrzResultRecordHeader.ID, 
            TempFrzResultRecordHeader."File Link", 
            TempFrzAttachmentResult
        );

        // Anhänge durchlaufen
        if TempFrzAttachmentResult.FindSet() then
            repeat
                //Verarbeitung der Anhänge
            until TempFrzAttachmentResult.Next() = 0;
    end else
        Message('Keine archivierten Anhänge für Rechnung %1 gefunden.', SalesInvoiceNo);
end;

Methode 2: GetSpecificRecordAttachment (Freeze API Mgt.)

Zweck

Lädt den tatsächlichen Inhalt eines spezifischen Anhangs als Base64-kodierten String herunter. Diese Methode wird typischerweise nach GetAttachments verwendet, um ausgewählte Anhänge herunterzuladen.

Verfügbare Überladungen

1. Mit automatischem Browser-Download

procedure GetSpecificRecordAttachment(FileLink: Text; AttachmentID: Guid; pFileName: Text): Text

2. Mit Kontrolle über Browser-Download

procedure GetSpecificRecordAttachment(FileLink: Text; AttachmentID: Guid; pFileName: Text; DownloadFromStream: Boolean): Text

Parameter

Parameter Typ Beschreibung
FileLink Text API-Link zum Datensatz (aus TempFrzAttachmentResult."File Link")
AttachmentID Guid Eindeutige Anhang-ID (aus TempFrzAttachmentResult.ID)
pFileName Text Dateiname für Download (aus TempFrzAttachmentResult.Filename)
DownloadFromStream Boolean true = Sofortiger Browser-Download; false = Nur Base64 zurückgeben

Rückgabewert

  • Text: Base64-kodierter Inhalt der Datei
  • Leerer String wenn Anhang nicht gefunden oder Fehler auftritt

Verwendungsbeispiele

Beispiel 1: Einzelnen Anhang sofort herunterladen

procedure DownloadFirstPDFAttachment(SalesInvoiceNo: Code[20])
var
    SalesInvoiceHeader: Record "Sales Invoice Header";
    TempFrzResultRecordHeader: Record "DXP FRZ Record Result Header" temporary;
    TempFrzResultRecordField: Record "DXP FRZ Result Record-Field" temporary;
    TempFrzResultQueryHeader: Record "DXP FRZ Query Result Header" temporary;
    TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary;
    FrzSearchMgt: Codeunit "DXP Freeze Search Mgt.";
    FrzResultMgt: Codeunit "DXP FRZ Result Mgt.";
    FrzApiMgt: Codeunit "DXP Freeze API Mgt.";
    QueryResult: JsonObject;
    SearchQuery: Text;
begin
    if not SalesInvoiceHeader.Get(SalesInvoiceNo) then
        Error('Rechnung %1 nicht gefunden.', SalesInvoiceNo);

    // Suchanfrage erstellen
    SearchQuery := FrzSearchMgt.GetSearchCombinationForTable(
        SalesInvoiceHeader.SystemId, 
        Database::"Sales Invoice Header"
    );

    // Freeze durchsuchen
    QueryResult := FrzApiMgt.SubmitSearch(SearchQuery);

    // Ergebnisse verarbeiten
    FrzResultMgt.CreateResult(
        QueryResult,
        TempFrzResultQueryHeader,
        TempFrzResultRecordHeader,
        TempFrzResultRecordField,
        TempFrzAttachmentResult,
        SearchQuery
    );

    // Nach PDF-Anhängen filtern
    TempFrzAttachmentResult.SetRange("File Extension", 'pdf');
    
    if TempFrzAttachmentResult.FindFirst() then begin
        // Direkter Download im Browser
        FrzApiMgt.GetSpecificRecordAttachment(
            TempFrzAttachmentResult."File Link",
            TempFrzAttachmentResult.ID,
            TempFrzAttachmentResult.Filename
        );
        
        Message('PDF-Anhang %1 wird heruntergeladen.', TempFrzAttachmentResult.Filename);
    end else
        Message('Keine PDF-Anhänge für Rechnung %1 gefunden.', SalesInvoiceNo);
end;

Beispiel 2: Base64-Inhalt für weitere Verarbeitung

procedure GetAttachmentAsBase64(RecordRef: RecordRef; var AttachmentBase64: Text; var AttachmentFilename: Text): Boolean
var
    TempFrzResultRecordHeader: Record "DXP FRZ Record Result Header" temporary;
    TempFrzResultRecordField: Record "DXP FRZ Result Record-Field" temporary;
    TempFrzResultQueryHeader: Record "DXP FRZ Query Result Header" temporary;
    TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary;
    FrzSearchMgt: Codeunit "DXP Freeze Search Mgt.";
    FrzResultMgt: Codeunit "DXP FRZ Result Mgt.";
    FrzApiMgt: Codeunit "DXP Freeze API Mgt.";
    SystemIdFieldRef: FieldRef;
    QueryResult: JsonObject;
    SystemId: Guid;
    SearchQuery: Text;
begin
    // SystemId aus RecordRef extrahieren
    SystemIdFieldRef := RecordRef.Field(RecordRef.SystemIdNo());
    SystemId := SystemIdFieldRef.Value();

    // Suchanfrage erstellen
    SearchQuery := FrzSearchMgt.GetSearchCombinationForTable(SystemId, RecordRef.Number());

    // Freeze durchsuchen
    QueryResult := FrzApiMgt.SubmitSearch(SearchQuery);

    // Ergebnisse verarbeiten
    FrzResultMgt.CreateResult(
        QueryResult,
        TempFrzResultQueryHeader,
        TempFrzResultRecordHeader,
        TempFrzResultRecordField,
        TempFrzAttachmentResult,
        SearchQuery
    );

    if TempFrzAttachmentResult.FindFirst() then begin
        // Base64-Inhalt abrufen OHNE Browser-Download
        AttachmentBase64 := FrzApiMgt.GetSpecificRecordAttachment(
            TempFrzAttachmentResult."File Link",
            TempFrzAttachmentResult.ID,
            TempFrzAttachmentResult.Filename,
            false  // Kein automatischer Download
        );

        AttachmentFilename := TempFrzAttachmentResult.Filename;
        exit(AttachmentBase64 <> '');
    end;

    exit(false);
end;

Spezialszenario: Ältesten PDF-Anhang herunterladen

Dieses Beispiel zeigt, wie Sie den ältesten (zuerst archivierten) PDF-Anhang eines Datensatzes finden und herunterladen.

Vollständiges Beispiel

procedure DownloadOldestPDFAttachment(RecordVariant: Variant): Boolean
var
    TempFrzResultRecordHeader: Record "DXP FRZ Record Result Header" temporary;
    TempFrzResultRecordField: Record "DXP FRZ Result Record-Field" temporary;
    TempFrzResultQueryHeader: Record "DXP FRZ Query Result Header" temporary;
    TempFrzAttachmentResult: Record "DXP FRZ Attachment Result" temporary;
    FrzSearchMgt: Codeunit "DXP Freeze Search Mgt.";
    FrzResultMgt: Codeunit "DXP FRZ Result Mgt.";
    FrzApiMgt: Codeunit "DXP Freeze API Mgt.";
    RecordRef: RecordRef;
    SystemIdFieldRef: FieldRef;
    QueryResult: JsonObject;
    SystemId: Guid;
    SearchQuery: Text;
    OldestArchiveDate: DateTime;
    AttachmentBase64: Text;
begin
    // RecordRef aus Variant erstellen
    RecordRef.GetTable(RecordVariant);

    // SystemId extrahieren
    SystemIdFieldRef := RecordRef.Field(RecordRef.SystemIdNo());
    SystemId := SystemIdFieldRef.Value();

    // Suchanfrage für diesen Datensatz erstellen
    SearchQuery := FrzSearchMgt.GetSearchCombinationForTable(SystemId, RecordRef.Number());

    // Freeze durchsuchen
    QueryResult := FrzApiMgt.SubmitSearch(SearchQuery);

    // Ergebnisse mit Anhängen abrufen
    FrzResultMgt.CreateResult(
        QueryResult,
        TempFrzResultQueryHeader,
        TempFrzResultRecordHeader,
        TempFrzResultRecordField,
        TempFrzAttachmentResult,
        SearchQuery
    );

    // Nach PDF-Anhängen filtern
    TempFrzAttachmentResult.SetRange("File Extension", 'pdf');

    if TempFrzAttachmentResult.IsEmpty() then begin
        Message('Keine PDF-Anhänge für diesen Datensatz gefunden.');
        exit(false);
    end;

    // Nach Archivierungsdatum aufsteigend sortieren (älteste zuerst)
    TempFrzAttachmentResult.SetCurrentKey("Archived at");
    TempFrzAttachmentResult.Ascending(true);

    // Ersten (ältesten) Anhang abrufen
    if TempFrzAttachmentResult.FindFirst() then begin
        OldestArchiveDate := TempFrzAttachmentResult."Archived at";

        Message('Ältester PDF-Anhang gefunden:\Datei: %1\Größe: %2 KB\Archiviert am: %3\Autor: %4',
            TempFrzAttachmentResult.Filename,
            Round(TempFrzAttachmentResult.Filesize / 1024, 1),
            OldestArchiveDate,
            TempFrzAttachmentResult.Author);

        // Anhang herunterladen
        AttachmentBase64 := FrzApiMgt.GetSpecificRecordAttachment(
            TempFrzAttachmentResult."File Link",
            TempFrzAttachmentResult.ID,
            TempFrzAttachmentResult.Filename,
            true  // Sofortiger Browser-Download
        );

        exit(AttachmentBase64 <> '');
    end;

    exit(false);
end;

Verwendung des Beispiels

// Von einer Verkaufsrechnung aus
var
    SalesInvoiceHeader: Record "Sales Invoice Header";
begin
    SalesInvoiceHeader.Get('SI-001');
    DownloadOldestPDFAttachment(SalesInvoiceHeader);
end;

// Von einer gebuchten Einkaufsrechnung aus
var
    PurchInvHeader: Record "Purch. Inv. Header";
begin
    PurchInvHeader.Get('PI-001');
    DownloadOldestPDFAttachment(PurchInvHeader);
end;

Zusammenfassung

Typischer Workflow

  1. Datensatz identifizieren: SystemId und TableNo des BC-Datensatzes ermitteln
  2. Suchanfrage erstellenFrzSearchMgt.GetSearchCombinationForTable()
  3. Freeze durchsuchenFrzApiMgt.SubmitSearch()
  4. Ergebnisse verarbeitenFrzResultMgt.CreateResult()
  5. Anhänge filtern: Filter auf TempFrzAttachmentResult setzen
  6. Anhänge herunterladenFrzApiMgt.GetSpecificRecordAttachment()