Donnerstag, 10. März 2011

Probleme beim Speichern von Dateien in einer MsSQL Datenbank

Selbstverständlich würde man sich heutzutage mehrmals überlegen, ob man Dateien in einer Datenbank als blob/binary speichert. Da ich an der Umstellung einer bestehenden PHP Applikation von PostgreSQL nach MsSQL arbeite und ein Umschreiben des bestehenden Codes keine Option war, musste ich also den bestehenden Mechanismus nach MsSQL transportieren. Die Lösungsmöglichkeiten für die aufgetretenen Probleme möchte ich kurz "sharen".

Größtes Problem war, dass gespeicherten Dateien beim Auslesen (Select) abgeschnitten wurden. Nach einigem Hin und Her mit verschiedenen Spaltentypen und dem Versuch mittels base64 Kodierung das Problem zu lösen bin ich nach langer Suche im Netz auf folgende Tatsachen gestoßen:
  • MsSQL benötigt eine spezielle Form, in der das File in die Query geschrieben wird
  • MsSQL schneidet per Default eben genau an einer bestimmten Stelle ab
Gelöst hab ich das Problem im Code so:

// Inhalt der Datei auslesen
$datastring = file_get_contents($_FILES["testfile"]["tmp_name"]);
// Weil MsSQL die Daten als "unquoted hexadecimal byte-string" erwartet
$data = unpack("H*hex", $datastring);

In der Query habe ich dann geschrieben:

$sql = "INSERT INTO dbo.test ([file]) VALUES (0x".$data['hex'].") ";

Damit die Dateien beim auslesen/abfragen aus der Datenbank nicht abgeschnitten werden, sollte man die entsprechenden php.ini Paramenter einstellen (mssql.textlimit und mssql.textsize). Diese stehen als Default meist auf 4000 oder 8000 Bytes.
Alternativ kann man auch per Query die textsize hochsetzen ("SET TEXTSIZE 2147483647;").




2 Kommentare:

  1. Klingt so, als sollte man sich mehrmals überlegen, MsSQL zu verwenden.

    Spaß beiseite, ist die Lösung nun DB-portabel?

    AntwortenLöschen
  2. Also ich mußte ja in einer bestehenden Applikation den Code umschreiben. Ich werde bald probieren, das Ganze nach Doctrine zu portieren, dann sollte es portabel sein.

    AntwortenLöschen