Klaus1: Wie kann ich Binary Daten aus SAP mit PHP zu einer PDF Datei konvertieren?

Hallo,

über eine RFC-Aufruf bekomme ich von SAP eine Tabelle zurück. In der Tabelle liegt die PDF-Datei augesplittet alle 1022 Zeichen.

Der Anfang der ersten Zeile sieht bspw. so aus:

255044462D312E370A25C7EC8FA20A352030206F626A0A3C3C2F4C656E6774682036203020522F466

Die Datei scheint also in Hex-Code übergeben worden zu sein. Die ersten Zeichen (25 50 44 46) sind der Hex-Ascii-Code für %PDF.

Also laufe ich durch alle Zeilen der Tabelle und wandle mittels hex2bin() um.

Aber der PDF-Reader erkennt das Dokument als fehlerhaft.

So sieht mein Script aus:

$rows = saprfc_table_rows ($fce,"CONTENT_BIN");
$pdfData = "";
for ($i=1;$i<=$rows;$i++) {
	$aline = saprfc_table_read ($fce,"CONTENT_BIN",$i);
	$pdfData .= hex2bin($aline["LINE"]);
}

$pdfName = "your_pdf_file_name.pdf";

header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=$pdfName");
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");

echo $pdfData;

Vergleiche ich diese PDF-Datei mit dem Original, dann werden einige Teile verschluckt.

Hat jemand eine Idee, woran das liegen kann?

LG Klaus

  1. Hallo Klaus1,

    ich kann es nicht testen, aber nach Augenschein sieht das PHP korrekt aus. Verschluckt jemand die Daten beim Speichern im SAP?

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      das PDF lässt sich manuell im SAP aufrufen und speichern. Im Moment muss ich erstmal davon ausgehen, dass SAP weiß, was es tut und die zurückgegebenen Daten innerhalb der Tabelle in Ordnung sind.

      Ich vermute, dass SAP die Daten in einem für PHP unerwartetem Format speichert. Vielleicht muss ich die Daten vorher/nachher noch zusätzlich umwandeln?

      In einem Editor geöffnet wird es ab Zeile 9 unterschiedlich. Original: :ÉûŸ«QÔﮘÒI®›('ÁÉÕ!LÖ(Ƕ*¶MÃ|˜Ý›ß^B“ß^þëÂïý®ýs' Mein Dokument: :ÉûŸ«QÔﮘÒI®›('ÁÉg´}p€••Œã?%WÐT‘Ú ~AâúgmÊKÖ‘B(

      LG Klaus

  2. Lieber Klaus1,

    über eine RFC-Aufruf bekomme ich von SAP eine Tabelle zurück.

    meinst Du eine Datenbank-Tabelle?

    In der Tabelle liegt die PDF-Datei augesplittet alle 1022 Zeichen.

    Das bedeutet, dass zuallererst alle Zeichen zusammengesetzt werden müssen, ehe man etwas anderes damit tut.

    $rows = saprfc_table_rows ($fce,"CONTENT_BIN");
    

    Was leistet die Funktion/Methode saprfc_table_rows? Allem Anschein nach liefert sie eine Ganzzahl, welche die Anzahl der Teildaten ermittelt.

    Frage: Kannst Du beweisen, dass $row auch wirklich die richtige Zahl liefert?

    $pdfData = "";
    for ($i=1;$i<=$rows;$i++) {
    	$aline = saprfc_table_read ($fce,"CONTENT_BIN",$i);
    	$pdfData .= hex2bin($aline["LINE"]);
    }
    

    Wenn $row die richtige Anzahl liefert, muss hier der Hase im Pfeffer liegen.

    1. Sind die benötigten Tabellen-Zeilen wirklich der Reihe nach in der Tabelle abgelegt? Also: Bekommst Du mit saprfc_table_read wirklich nur die betroffenen Zeilen, und sind diese fortlaufend nummeriert, dass $i keine fremden Zeilen einliest (und dafür andere auslässt)?
    2. Warum sammelst Du nicht die PDF-Daten zuerst vollständig in einer Variable, ehe Du hex2bin darauf anwendest? Wenn die Anzahl der Zeichen aus welchem Grund auch immer ungerade sein sollte, dann könnte es sein, dass Du fehlerhafte Teildaten generierst, weil „halbe Bytes“ zu ganzen Bytes umgewandelt werden (1a2b3 + c4d5e => 1a 2b 03 + c4 d5 06 anstatt 1a 2b 3c 4d 5e). Also zuerst alles in einen String einlesen und dann hex2bin anwenden.

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix,

      das könnte man debuggen: liefert die read Funktion stets eine gerade Zahl von Bytes zurück und ist die Aussage "alle 1022 Bytes" der Realität entsprechend.

      Statt mit einem Editor sollte man mit einem hex-fähigen Fileviewer prüfen, ob die Abweichung genau an einer 1022-Byte Grenze auftritt.

      Ob SAP richtig anprogrammiert wird, wird hier außer Klaus wohl keiner wissen…

      Rolf

      --
      sumpsi - posui - obstruxi
    2. Hallo Felix,

      meinst Du eine Datenbank-Tabelle?

      Nein, es ist eine Tabellen-Struktur, die von SAP-Funktionsbaustein zurückgegeben wird.

      In der Tabelle liegt die PDF-Datei augesplittet alle 1022 Zeichen.

      Das bedeutet, dass zuallererst alle Zeichen zusammengesetzt werden müssen, ehe man etwas anderes damit tut.

      Ich hatte zuerst auch den zusammengesetzten String mit hex2bin() umgewandelt, aber nachdem es nicht funktioniert hat, dann auf jede einzelne Zeile übergegangen. Da SAP die Daten auch nicht komplett in einen String gepackt hat, sondern in (in meinem Fall) 60 Zeilen aufgeteilt hat.

      $rows = saprfc_table_rows ($fce,"CONTENT_BIN");
      

      Was leistet die Funktion/Methode saprfc_table_rows? Allem Anschein nach liefert sie eine Ganzzahl, welche die Anzahl der Teildaten ermittelt.

      Richtig, es liefert die Anzahl der zurückgegebenen Zeilen.

      Frage: Kannst Du beweisen, dass $row auch wirklich die richtige Zahl liefert?

      Hmm, beweisen nicht, aber das ist das, was auch im SAP angezeigt wird, wenn ich den Funktionsbaustein im SAP (Transaktion SE37) aufrufe.

      $pdfData = "";
      for ($i=1;$i<=$rows;$i++) {
      	$aline = saprfc_table_read ($fce,"CONTENT_BIN",$i);
      	$pdfData .= hex2bin($aline["LINE"]);
      }
      

      Wenn $row die richtige Anzahl liefert, muss hier der Hase im Pfeffer liegen.

      1. Sind die benötigten Tabellen-Zeilen wirklich der Reihe nach in der Tabelle abgelegt? Also: Bekommst Du mit saprfc_table_read wirklich nur die betroffenen Zeilen, und sind diese fortlaufend nummeriert, dass $i keine fremden Zeilen einliest (und dafür andere auslässt)?

      Wenn ich die Quelltexte der beiden PDF-Dateien (manuell aus SAP und über den Funktionsbaustein gespeichert) vergleiche, dann sieht die Reihenfolge nicht vertauscht aus. Aber es fehlen Daten (oder sind anders kodiert?). DIe Größe hat sich nahezu halbiert (60.646 bytes zu 30.660).

      1. Warum sammelst Du nicht die PDF-Daten zuerst vollständig in einer Variable, ehe Du hex2bin darauf anwendest?

      In jeder Zeile sind genau 1022 Zeichen. Daher sollte es theorteisch kein Problem gegeben haben. Praktisch auch nicht. Beide Dateien (hex2bin je Zeile oder mit gesamten String) sind identisch.

      LG Klaus

      1. Lieber Klaus,

        eine Sache würde ich noch prüfen, um die Gültigkeit Deiner Grundannahme (Binärdaten als Hex-Repräsentation in 1022er-Chunks in Tabellenzeilen geschrieben) zu validieren.

        1. Schreibe die Hex-Repräsentation in eine Textdatei.
        2. Vergleiche Hex-Repräsentation in der Textdatei mit der Hex-Repräsentation in einem Hexviewer, der die aus SAP heruntergeladene PDF-Datei anzeigt.

        Wenn ich die Quelltexte der beiden PDF-Dateien (manuell aus SAP und über den Funktionsbaustein gespeichert) vergleiche, dann sieht die Reihenfolge nicht vertauscht aus. Aber es fehlen Daten (oder sind anders kodiert?). DIe Größe hat sich nahezu halbiert (60.646 bytes zu 30.660).

        Bis wohin findest Du denn Übereinstimmungen? Passen die Hex-Werte der ganzen ersten 1022 Zeichen (511 Bytes)? Scheint jedenfalls nicht so...

        Liebe Grüße

        Felix Riesterer

        1. Hallo Felix,

          ich habe mir die "Tabelle"im SAP angeschaut... Die erste Zeile hört mit ...27C1C9 auf. Die zweite Zeile fängt mit 6705B4... an. Dann im Hexeditor geprüft: Im funktionierenden Original endet 27C1C9 an Position 1FE (Dezimal 510) und 6705B4 startet ab Position 3FE (Dezimal 1022) Position 511 startet mit D5214C. In den 60 Zeilen ist diese Kombination nicht zu finden. Scheinbar liefert da SAP doch keine vollständigen Daten. Man sich wohl auf ga nichts verlassen. 😜 Das werde ich dann auf SAP-Seite weiter analysieren müssen.

          Vielen Dank.

          LG Klaus