PHP-Logo
Druckansicht von http://www.php-homepage.de/artikel/artikel10.html

PHP-Logo
[ Main Menue ]
Homepage
Downloads
Artikel
Scripts
Forum
PHP-Manual
Links
News
Freelancer
Bücher
RuDolF
Suche
Misc
Über diese Seite
Kontakt
Wunschzettel
MyGuestbook
*
[ Suche ]
*
[ Partner ]


Domain Webhosting
*
[ Partner Sites ]
Dynamic-Webpages
PHP-Center
PHP-Welt
phpUG.de
Random Link
*
[ Autoren gesucht! ]
PHP-Homepage.de sucht laufend Autoren für News und Artikel
Interesse?
*

Follow on Twitter - @phphomepage

RSS Feed blogoscoop

Oracle Intermedia mit PHP nutzen von Andreas Schmitz

Von Andreas Schmitz <andreas.schmitz@as-dataservice.de>

1    Relationale Datenbank mit multimedialem Inhalt

Wenn die Begriffe SQL und Datenbank fallen, denkt jeder in erster Linie an trockene Datengebilde, wie die Adressenverwaltung, Artikelmanagement und eben die typischen Anwendungen einer relationalen Datenbank. Diese Anwendungen eignen sich für eine Datenbank auch hervorragend, da die Daten sehr einfach in Attributen, die für jede Zeile eine einheitliche Speichergröße haben, Platz finden können.
Anders sieht es hingegen bei dynamischen Attributslängen aus. Möchte man z. B. ein Bild in einer Datenbank ablegen, so kann nicht einfach ein Attribut mit einer fest definierten Größe reserviert werden, wie das z. B. bei dem Attribut „Vorname“ möglich ist. Vielmehr muss die Datenbank in der Lage sein, binäre Daten einer beliebigen Länge dynamisch verwalten zu können. Viele Datenbanken bieten hierfür die Large Objects (LOB) an. Als Datentyp wählt man hier also nicht VARCHAR, INTEGER oder FLOAT, sondern BLOB (BLOB = Binary Large Objcet und dient zum Speichern von reinen Binärdaten) und erhält ein Attribut, welches in jeder Zeile eine andere Speichergröße haben kann. Die Größe richtet sich - getrennt für jede Zeile - nach den eingefügten Daten in eben diesem LOB.
Diese LOB’s eignen sich fabelhaft, um dynamischen Inhalt in eine Datenbank einzupflegen und zu verwalten. Mit Hilfe dieser Technik könnte man z. B. ein Bild eines jeden Kunden oder aber ein gesprochenes Audiofile mit jedem Produkt in der Datenbank hinterlegen, welches die Vorzüge dieses Produktes audiotechnisch beschreibt.

2    Was ist Oracle interMedia

Beschränken sich viele Datenbankhersteller auf LOB’s, so bietet Oracle mit interMedia die Möglichkeit, diese multimedialen Elemente – wenn Sie denn mal in der Datenbank sind – zu bearbeiten. Die Änderungen reichen von der Dateiformatkonvertierung (ein GIF kann in ein JPG gewandelt werden) über das Komprimieren und das Skalieren von Bildern. Fügt man z. B. ein TIF Bild mit der Auflösung 640x480 in die Datenbank ein, so ist es möglich, dieses später als JPG mit der Auflösung 320x240 auszugeben; natürlich müssen auch evtl. Performance-Überlegungen bei der Modellierung eines solchen Vorhabens berücksichtigt werden. Aber gerade auf einer dynamisch gestalteten Website kann der Webentwickler diese Skalierungstechniken sicherlich gut verwenden.
Wenn geplant ist, ein Content-Management-System zu entwickeln, können sich die mediabearbeitenden Möglichkeiten von Oracle schon alleine dadurch auszahlen, dass sich der Programmierer der Clientsoftware, (die vielleicht noch in einer handelsüblichen 3GL Sprache wie VisualBasic entwickelt wird), um bildbearbeitende Funktionen nicht zu kümmern braucht.

2.1  Objektrationales Datenbankdesign

Oracle verwendet bei interMedia die objektrationalen Eigenschaften von Oracle 8i. Die wichtigsten Objekte von interMedia sind:
  • ORDAudio: Objekt zur Verwaltung von Audiodaten (.wav usw.)
  • ORDImage: Objekt zur Verwaltung von Bilddaten (.jpg, .gif, .bmp usw.)
  • ORDVideo: Objekt zur Verwaltung von Videos (.avi, .rnm usw.)
Gemeinsam ist diesen Objekten, dass jedes von Ihnen die Möglichkeit bietet, die Daten lokal als BLOB unter der Transaktionskontrolle von Oracle oder als BFILE, bei welchem das Datenmaterial außerhalb der Datenbank gespeichert wird, zu speichern. Die Methoden jedes einzelnen Objektes unterscheiden sich; wohl wegen den verschiedenen unterschiedlichen Eigenheiten eines jeden Mediatyps.
Welche Formate unterstützt werden, kann man in der mitgelieferten Oracledokumentation in dem Kapitel Oracle8i interMedia Audio, Image, and Video User's Guide and Reference nachlesen.

2.2  Verwendung von interMedia

Um Mediadaten in die Datenbank einzufügen oder wieder auszulesen kann jede Sprache herangezogen werden, die in der Lage ist, LOBs mit der bereitgestellten Oracle-Datenbankschnittstelle zu verwalten. Neben C/C++, welche dank der direkten Kommunikationsmöglichkeit über die OCI (= Oracle Call Interface) wohl die flexibelsten Möglichkeiten bietet, kann auch die für Internetanwendungen weit verbreitete Scriptsprache PHP mit ihrer guten Kapselung der OCI8 eingesetzt werden. Das Beispiel, welches in diesem Artikel später vorgestellt wird, zeigt dies detailliert anhand des interMedia Objektes ORDImage.

3    Installation von Oracle interMedia

Oracle interMedia kann während des Datenbankeinrichtens oder aber nachträglich bei einer bestehenden Datenbank installiert werden. Folgende Schritte sind hierzu nötig:
  1. Java Server: Installieren Sie den Oracle Java Server. Nähere Informationen hierzu finden Sie in der Datei: $ORACLE_HOME/javavm/doc/readme.txt.
  2. interMedia: Nachdem der Java Server erfolgreich installiert wurde, werden die interMedia Objekte installiert, indem Sie die Datei $ORACLE_HOME/ord/im/admin/README.txt aufmerksam lesen und die Anweisungen befolgen.

Diese beiden Schritte können auch automatisch über den Migration Assistent mit einer Grafischen Benutzeroberfläche von Oracle – odma – ausgeführt werden.
Sehr wichtig ist, dass anschließend die tnsnames.ora und listener.ora dahingehend geändert werden, dass Oracle in der Lage ist, eine IPC-Verbindung zu dem Listenerprozess herzustellen, da die verschiedenen Funktionen von interMedia extern ausgelagert wurden. Wie das geht und was genau zu beachten ist, kann in der Oracle Referenz, - Net8 Administrator's Guide, Kapitel 8 „Enabling Advanced Net8 Features, Configuring Net8 for External Procedures“ nachgelesen werden.
Stimmt etwas mit der Net8 Konfiguration nicht, so erhalten Sie beim Aufruf der interMedia-Funktionen eine Fehlermeldung, welche Ihnen sagt, dass Probleme mit der IPC-Verbindung aufgetreten sind.
Bitte achten Sie darauf, dass Oracle bei der Einrichtung des Java Servers und interMedia Benutzer mit Standardpasswörtern anlegt. Sie sollten diese nach der Installation unbedingt ändern.

4 Beispielscript in PHP für ORDImage

Das Beispiel, welches in PHP realisiert wurde, zeigt, wie Bilder in die Oracle Datenbank einfügt und an dem eingefügten Bild Änderungen durchführt werden. Anschließend verdeutlicht das Beispielscript, wie Bilder, die in der Datenbank abgelagert wurden, in einem Webbrowser anzeigt werden. Eine lauffähige Version kann unter http://intermedia.as-dataservice.de sofort ausprobiert werden.

4.1 Voraussetzungen

Um das Beispiel selbst zu installieren und zu testen wird PHP 4.0.4pl1 mit der OCI8 (--with-OCI8) Unterstützung benötigt. track_vars sollte auf On gesetzt sein und das Sessionsmanagement wird ohne Cookies realisiert.

4.2 Das Erzeugen der Tabelle

Um das Beispiel selbst auszuprobieren, wird lediglich der Datentyp ORDImage bei der Spaltendefinition zusätzlich verwendet:

CREATE TABLE BILD

    BILDID VARCHAR2 (64) NOT NULL, 
    IMAGE ORDSys.ORDImage NOT NULL, 
    CONSTRAINT PK_BILD2 PRIMARY KEY (BILDID)
);

Es wurde hier - der Einfachheit halber - ein textbezogener Primary-Key verwendet, weil in diesem Feld die von PHP erzeugte SessionID hinterlegt wird. Da das Bild in einen BLOB, welches sich in der Objektdefinition befindet, gespeichert wird, kann hier auch bestimmt werden, in welchem Tablespace dieses LOB geschrieben werden soll (LOB Clause).

4.3 Das einfügen eines Bildes

Mit OCINewDescriptor wird Speicher reserviert, um eine LOB-Referenz in PHP abzulegen. Nach dem Einfügen eines leeren Datensatzes muss mit SELECT ... FOR UPDATE der Datensatz gelesen werden, um die Zeile bis zum Commit oder Rollback zu blockieren (lock).

$blob = OCINewDescriptor ($oraSession,OCI_D_LOB);

$stmt=" DECLARE
            iimage ORDSys.ORDImage;
            iblob BLOB;
        BEGIN
            DELETE bild
            WHERE bildid='$sSessionid';

            INSERT INTO bild
            (bildid,image)
            VALUES
            ('$sSessionid',ordsys.ordImage(ORDSYS.ORDSource
            (EMPTY_BLOB(),
            NULL,NULL,NULL,SYSDATE,1),
            NULL,NULL,NULL,NULL,NULL,NULL,NULL));

            SELECT image
            INTO iimage
            FROM bild
            WHERE bildid='$sSessionid'
            FOR UPDATE;

            iblob := iimage.source.localData;
            :extblob:=iblob
        END; ";

$stmt = strtr ($stmt,chr(13).chr(10)," ");

$oraParse=OCIParse($oraSession,$stmt);
OCIBindByName ($oraParse,':extblob',&$blob,-1,OCI_B_BLOB);
OCIExecute ($oraParse,OCI_DEFAULT);
$blob->savefile($sFilename);
OCIFreeStatement ($oraParse);
OCIFreeDesc ($blob);

Nachdem eine neue Zeile eingefügt wurde, wird mit $blob->savefile($sFilename) die durch das Formular übertragene Datei in das BLOB geschrieben. Das Objekt $blob stellt auch die Methode „save()“ zur Verfügung, mit der der Inhalt einer Variable geschrieben werden kann. 
Leider überprüft interMedia nicht die Gültigkeit der eingefügten Daten, daher findet sich im Beispiel auch anschließend ein SELECT ... FOR UPDATE, welches das eingefügte Bildmaterial lädt und eine Methode zum Skalieren um den Faktor 1.0 (verursacht technisch keine Veränderung) anwendet. Wird hier ein Fehler zurück geliefert, so kann man davon ausgehen, dass Oracle das eingefügte Bildformat nicht kennt. Sicher bietet Oracle mit der Methode properties() die Möglichkeit, das eingefügte Bildformat zu analysieren, nur funktioniert das nicht bei Progessive vorhandenen JPG Bildern. Diese erkennt Oracle als JPG, kann sie aber nicht verarbeiten, da Oracle JPG-Bilder nur mit einer Standardkodierung verarbeiten kann.

4.4 Das Ändern eines in der Datenbank enthaltenen Bildes

Könnte man die eingelesenen Bilder in der Datenbank nur wieder ausgeben, würde interMedia sicherlich keinen großen Nutzen bringen. Vielmehr hat der Programmierer mit der process()-Methode die Möglichkeit, an dem eingefügten Bild direkt Änderungen durchzuführen. Diese Änderungen könnten auch in PL/SQL Prozeduren gekapselt werden.
Erst mal muss das Objekt geladen werden:

SELECT image
INTO iImage
FROM bild
WHERE bildid='$sSessionid'
FOR UPDATE;

Nachdem das Objekt mit dem Bild geladen und in der Variable iImage die Referenz geschrieben wurde, kann durch einfaches Aufrufen von process() die Eigenschaft geändert werden.

iImage.process('fileFormat=JFIF, compressionFormat=JPEG,
compressionQuality=LOWCOMP');

Dieser Aufruf wandelt das Bild in ein JPEG mit einer niedrigen Kompressionsrate um. Um das Ergebnis anschließend in der Datenbank festzuhalten, sollte mit einem abschließenden UPDATE das Objekt zurück geschrieben werden:

UPDATE bild
SET image = iImage
WHERE bildid='$sSessionid';

Wird jetzt ein OCICommit($oraSession); an die Datenbank gesendet, ist das geänderte Bild dauerhaft gespeichert.

4.5 Anzeigen eines Bildes im Browser

Für die Ausgabe des Bildes habe ich eine PL/SQL Funktion geschrieben, um zu zeigen, dass man die Business Logik auch auf die Datenbank auslagern kann. Folgende Stored Procedure muss daher auf der Datenbank eingerichtet werden:

CREATE OR REPLACE FUNCTION GetPicture
                           (OUT_Mimetype OUT VARCHAR2,
                            IN_sessionid IN VARCHAR2)
                  RETURN blob
AS
    oImage ORDsys.ordImage;
BEGIN
        SELECT image
        INTO oImage
        FROM BILD
        WHERE bildid=IN_SessionID;

        OUT_Mimetype := oImage.getMimetype;
        RETURN oImage.getcontent;
END GetPicture;

Diese Funktion lieferte als Ausgabewerte einerseits das BLOB mit den Bilddaten und anderseits den Mimetype (z. B. image/jpeg), welcher im Header an den Browser gesendet werden muss, damit dieser weiß, um was für Daten es sich hier handelt. Als erstes muss auch hier ein Descriptor reserviert werden. Anschließend wird die in die Datenbank eingefügte Funktion GetPicture aufgerufen.

$blob = OCINewDescriptor ($oraSession,OCI_D_LOB);
$stmt = " DECLARE
            sMimetype VARCHAR2(10);
          BEGIN
            :extblob:=GetPicture(sMimetype,'$sSessionid');
            :sMimetype:=sMimetype;
          END; ";
$stmt = strtr ($stmt,chr(13).chr(10)," "); 
$oraParse=OCIParse($oraSession,$stmt);
OCIBindByName ($oraParse,':extblob',&$blob,-1,OCI_B_BLOB);
OCIBindByName ($oraParse,':sMimetype',&$sMimetype,10);
OCIExecute ($oraParse,OCI_DEFAULT);
$BinaryBild = $blob->load();

Nach dem erfolgreichen Ausführen dieses Statements befindet sich in der Variable $BinaryBild das komplette Bild. Jetzt muss diese nur noch ausgegeben werden:

header ("Content-Type: ".$sMimetag);
echo $BinaryBild;

Wichtig ist, dass ein Header nur dann an den Browser gesendet werden kann, wenn zuvor noch keine Ausgabe getätigt wurde. Das Header-Tag „Content-Type“ muss unbedingt an den Browser gesendet werden, damit dieser auch erkennt, um was für einen Inhalt es sich hier handelt.

5 Weitere Verwendungsmöglichkeiten

Bei dem eben gezeigten Beispiel sollte nur vereinfacht gezeigt werden, wie man interMedia – hier ORDImage – verwendet und ist auch noch stark ausbaufähig. Es zeigt aber anschaulich, zu welchen Dingen interMedia fähig ist. Die Ideen für weitere Verwendungen sind sehr vielfältig. Anzumerken ist auch, dass die Konvertierung in eine JPEG Kompression auch Zeit in Anspruch nimmt. Da in den meisten Fällen das Anzeigen der Bilder gegenüber dem Einfügen überwiegt, sollte schon direkt nach dem Einfügen das entsprechende Bildmaterial in das benötigte Ausgabeformat konvertiert werden.
Benötigt man kleinere Vorschaubilder, so spricht nichts dagegen, zwei ORDImage Attribute, eines für das kleine Bild und das andere für das größere Bild, in eine Tabelle zu integrieren. So erspart man sich beim Anzeigen des kleinen und des großen Bildes das Konvertieren; Speicherplatz sollte hier kein Problem darstellen, da kleine Vorschaubilder mit einer JPEG Kompression meist nur 2 – 3 KByte in Anspruch nehmen.


Zurück zur Übersicht
© Copyright 1999 - 2011 by Mark Kronsbein | Impressum | NutzungsbedingungenWeiterempfehlen | Seitenanfang
0.0222