<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="zend.file.transfer.introduction">
    <title>Zend_File_Transfer</title>

    <para>
        <classname>Zend_File_Transfer</classname> bietet exzessiven Support für Datei Uploads und
        Downloads. Es kommt mit eingebauten Prüfungen für Dateien und Funktionslitäten um Dateien
        mit Filtern zu verändern. Protokoll-Adapter erlauben
        <classname>Zend_File_Transfer</classname> die selbe <acronym>API</acronym> für
        Transportprotokolle wie <acronym>HTTP</acronym>, FTP, WEBDAV und andere zu verwenden.
    </para>

    <note>
        <title>Einschränkungen</title>

        <para>
            Die aktuelle Implementation von <classname>Zend_File_Transfer</classname>
            ist auf <acronym>HTTP</acronym> Post Uploads limitiert. Andere Adapter die Downloads und
            andere Protokolle unterstützen werden in zukünftigen Releases hinzugefügt. Aktuell
            sollte <classname>Zend_File_Transfer_Adapter_Http</classname> direkt verwendet werden.
            Sobald andere Adapter vorhanden sind, kann ein gemeinsames Interface verwendet werden.
        </para>
    </note>

    <note>
        <title>Formulare</title>

        <para>
            Wenn man <classname>Zend_Form</classname> verwendet sollte man die
            <acronym>API</acronym>s die von <classname>Zend_Form</classname> zur Verfügung gestellt
            werden, und <classname>Zend_File_Transfer</classname> nicht direkt, verwenden. Der
            Dateitransfer Support von <classname>Zend_Form</classname> ist in
            <classname>Zend_File_Transfer</classname> implementiert, weshalb die Informationen in
            diesem Kapitel für fortgeschrittene Benutzer von <classname>Zend_Form</classname>
            interessant sind.
        </para>
    </note>

    <para>
        Die Verwendung von <classname>Zend_File_Transfer</classname> ist relativ einfach. Es besteht
        aus zwei Teilen. Dem <acronym>HTTP</acronym> Formular, während
        <classname>Zend_File_Transfer</classname> die hochgeladenen Dateien behandelt. Siehe das
        folgende Beispiel:
    </para>

    <example id="zend.file.transfer.introduction.example">
        <title>Einfaches Formular für File-Uploads</title>

        <para>
            Dieses Beispiel zeigt einen einfachen Dateiupload. Das erste Teil ist das Dateiformular.
            In unserem Beispiel gibt es nur eine Datei welche wir hochladen wollen.
        </para>

        <programlisting language="xml"><![CDATA[
<form enctype="multipart/form-data" action="/file/upload" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="100000" />
        Choose a file to upload: <input name="uploadedfile" type="file" />
    <br />
    <input type="submit" value="Upload File" />
</form>
]]></programlisting>

        <para>
            Der Bequemlichkeit halber kann
            <link linkend="zend.form.standardElements.file">Zend_Form_Element_File</link> verwendet
            werden statt das <acronym>HTML</acronym> manuell zu erstellen.
        </para>

        <para>
            Der nächste Schritt ist die Erstellung des Empfängers des Uploads. In unserem Beispiel
            ist der Empfänger bei <filename>/file/upload</filename> zu finden. Als nächstes
            erstellen wir also den 'file' Controller mit der <methodname>upload()</methodname>
            Aktion.
        </para>

        <programlisting language="php"><![CDATA[
$adapter = new Zend_File_Transfer_Adapter_Http();

$adapter->setDestination('C:\temp');

if (!$adapter->receive()) {
    $messages = $adapter->getMessages();
    echo implode("\n", $messages);
}
]]></programlisting>

        <para>
            Dieses Codebeispiel demonstriert die einfachste Verwendung von
            <classname>Zend_File_Transfer</classname>. Ein lokales Ziel wird mit der
            <methodname>setDestination()</methodname> Methode definiert, und anschließend die
            <methodname>receive()</methodname> Methode aufgerufen. Wenn irgendwelche Uploadfehler
            auftreten werden diese als Ausnahme zurückgegeben.
        </para>
    </example>

    <note>
        <title>Achtung</title>

        <para>
            Dieses Beispiel ist nur für die Demonstration der grundsätzlichen <acronym>API</acronym>
            von <classname>Zend_File_Transfer</classname>. Man sollte dieses Code Beispiel
            <emphasis>niemals</emphasis> in einer Produktivumgebung einsetzen da es massive
            Sicherheitslücken aufweisst. Man sollte immer Prüfungen verwenden um die Sicherheit
            zu erhöhen.
        </para>
    </note>

    <sect2 id="zend.file.transfer.introduction.adapters">
        <title>Von Zend_File_Transfer unterstützte Adapter</title>

        <para>
            <classname>Zend_File_Transfer</classname> wurde designt um verschiedenste Adapter und
            auch Richtungen zu unterstützen. Mit <classname>Zend_File_Transfer</classname> kann man
            Dateien Hochladen, Herunterladen und sogar Weiterleiten (Hochladen mit einem Adapter und
            Herunterladen mit einem anderen Adapter zur gleichen Zeit).
        </para>
    </sect2>

    <sect2 id="zend.file.transfer.introduction.options">
        <title>Optionen für Zend_File_Transfer</title>

        <para>
            <classname>Zend_File_Transfer</classname> und seine Adapter unterstützen verschiedene
            Optionen. Alle Optionen können gesetzt werden indem Sie entweder dem Constructor
            übergeben werden, oder durch Aufruf der <methodname>setOptions($options)</methodname>.
            <methodname>getOptions()</methodname> gibt die Optionen zurück die aktuell gesetzt
            sind. Nachfolgend ist eine Liste aller unterstützten Optionen:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <emphasis>ignoreNoFile</emphasis>: Wenn diese Option auf
                    <constant>TRUE</constant> gesetzt ist, ignorieren alle Prüfer Dateien die nicht
                    vom Formular hochgeladen wurde. Der Standardwert ist <constant>FALSE</constant>,
                    was einen Fehler verursacht wenn die Datei nicht spezifiziert wurde.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.file.transfer.introduction.checking">
        <title>Dateien prüfen</title>

        <para>
            <classname>Zend_File_Transfer</classname> hat verschiedene Methoden die auf
            verschiedenste Stati von spezifizierten Dateien prüfen. Diese sind nützlich wenn man
            Dateien bearbeiten will nachdem Sie empfangen wurden. Diese Methoden beinhalten:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <emphasis>isValid($files = null)</emphasis>: Diese Methode prüft ob die
                    angegebene Datei gültig ist, basierend auf den Prüfungen welche dieser Datei
                    angehängt sind. Wenn keine Dateien spezifiziert wurden, werden alle Dateien
                    geprüft. Man kann <methodname>isValid()</methodname> aufrufen bevor
                    <methodname>receive()</methodname> aufgerufen wird; in diesem Fall ruft
                    <methodname>receive()</methodname> intern <methodname>isValid()</methodname>
                    nicht mehr auf.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>isUploaded($files = null)</emphasis>: Diese Methode prüft ob die
                    spezifizierte Datei vom Benutzer hochgeladen wurde. Das ist nützlich wenn man
                    eine oder mehrere Dateien definiert hat. Wenn keine Dateien spezifiziert wurden,
                    werden alle Dateien geprüft.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>isReceived($files = null)</emphasis>: Diese Methode prüft ob die
                    spezifizierte Datei bereits empfangen wurde. Wenn keine Dateien angegeben
                    wurden, werden alle Dateien geprüft.
                </para>
            </listitem>
        </itemizedlist>

        <example id="zend.file.transfer.introduction.checking.example">
            <title>Dateien prüfen</title>

            <programlisting language="php"><![CDATA[
$upload = new Zend_File_Transfer();

// Gibt alle bekannten internen Datei Informationen zurück
$files = $upload->getFileInfo();

foreach ($files as $file => $info) {
    // Datei hochgeladen ?
    if (!$upload->isUploaded($file)) {
        print "Warum hast Du die Datei nicht hochgeladen ?";
        continue;
    }

    // Prüfungen sind ok ?
    if (!$upload->isValid($file)) {
        print "Sorry, aber die Datei ist nicht das was wir wollten";
        continue;
    }
}

$upload->receive();
]]></programlisting>
        </example>
    </sect2>

    <sect2 id="zend.file.transfer.introduction.informations">
        <title>Zusätzliche Dateiinformationen</title>

        <para>
            <classname>Zend_File_Transfer</classname> kann zusätzliche Informationen über Dateien
            zurückgeben. Die folgenden Methoden sind vorhanden:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <emphasis>getFileName($file = null, $path = true)</emphasis>: Diese Methode
                    gibt den wirklichen Namen der übertragenen Datei zurück.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>getFileInfo($file = null)</emphasis>: Diese Methode gibt die
                    internen Informationen für die angegebene übertragene Datei zurück.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>getFileSize($file = null)</emphasis>: Diese Methode gibt die
                    echte Dateigröße für die angegebene Datei zurück.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>getHash($hash = 'crc32', $files = null)</emphasis>: Diese Methode
                    gibt einen Hash des Inhalts einer angegebenen übertragenen Datei zurück.
                </para>
            </listitem>

            <listitem>
                <para>
                    <emphasis>getMimeType($files = null)</emphasis>: Diese Methode gibt den
                    Mimetyp der angegebenen übertragenen Datei zurück.
                </para>
            </listitem>
        </itemizedlist>

        <para>
            <methodname>getFileName()</methodname> akzeptiert den Namen des Elements als ersten
            Parameter. Wenn kein Name angegeben wird, werden alle bekannten Dateinamen in einem
            Array zurückgegeben. Wenn die Datei eine MultiDatei ist, wird auch ein Array
            zurückgegeben. Wenn nur eine einzelne Datei vorhanden ist wird nur ein String
            zurückgegeben.
        </para>

        <para>
            Standardmäßig werden Dateinamen mit dem kompletten Pfad zurückgegeben. Wenn man nur den
            Dateinamen ohne Pfad benötigt, kann der zweite Parameter <varname>$path</varname>
            gesetzt werden, welcher den Dateinamen ausschneidet wenn er auf
            <constant>FALSE</constant> gesetzt wird.
        </para>

        <example id="zend.file.transfer.introduction.informations.example1">
            <title>Den Dateinamen bekommen</title>

            <programlisting language="php"><![CDATA[
$upload = new Zend_File_Transfer();
$upload->receive();

// Gibt die Dateinamen aller Dateien zurück
$names = $upload->getFileName();

// Gibt den Dateinamen des Formularelements 'foo' zurück
$names = $upload->getFileName('foo');
]]></programlisting>
        </example>

        <note>
            <para>
                Es ist zu beachten das sich der Dateinamen ändern kann nachdem die Datei empfangen
                wurde (receive) weil alle Filter angewendet werden, sobald die Datei empfangen
                wurde. Deswegen sollte man <methodname>getFileName()</methodname> immer ausführen
                nachdem die Dateien empfangen wurden.
            </para>
        </note>

        <para>
            <methodname>getFileSize()</methodname> gibt standardmäßig die echte Dateigröße in SI
            Schreibweise zurück was bedeutet das man <emphasis>2kB</emphasis> statt
            <emphasis>2048</emphasis> erhält. Wenn man die reine Größe benötigt muß man die
            <property>useByteString</property> Option auf <constant>FALSE</constant> setzen.
        </para>

        <example id="zend.file.transfer.introduction.informations.example.getfilesize">
            <title>Die Größe einer Datei erhalten</title>

            <programlisting language="php"><![CDATA[
$upload = new Zend_File_Transfer();
$upload->receive();

// Gibt die Größen aller Dateien als Array zurück
// wenn mehr als eine Datei hochgeladen wurde
$size = $upload->getFileSize();

// Wechsle die SI Schreibweise damit reine Nummern zurückgegeben werden
$upload->setOptions(array('useByteString' => false));
$size = $upload->getFileSize();
]]></programlisting>
        </example>

        <note>
            <title>Vom Client angegebene Dateigröße</title>

            <para>
                Es ist zu beachten das die Dateigröße welche vom Client angegeben wird, nicht als
                sichere Eingabe angesehen wird. Deswegen wird die echte Größe der Datei erkannt und
                statt der Dateigröße zurückgegeben welche vom Client geschickt wurde.
            </para>
        </note>

        <para>
            <methodname>getHash()</methodname> akzeptiert den Namen eines Hash Algorithmus als
            ersten Parameter. Für eine Liste bekannter Algorithmen kann in
            <ulink url="http://php.net/hash_algos">PHP's hash_algos Methode</ulink> gesehen werden.
            Wenn kein Algorithmus spezifiziert wird, wird <emphasis>crc32</emphasis> als
            Standardalgorithmus verwendet.
        </para>

        <example id="zend.file.transfer.introduction.informations.example2">
            <title>Den Hash einer Datei erhalten</title>

            <programlisting language="php"><![CDATA[
$upload = new Zend_File_Transfer();
$upload->receive();

// Gibt die Hashes von allen Dateien als Array zurück
// wenn mehr als eine Datei hochgeladen wurde
$hash = $upload->getHash('md5');

// Gibt den Has für das 'foo' Formularelement zurück
$names = $upload->getHash('crc32', 'foo');
]]></programlisting>
        </example>

        <note>
            <title>Rückgabewert</title>

            <para>
                Es ist zu beachten das der zurückgegebene Wert ein Array ist, wenn die Datei oder
                der Formularname mehr als eine Datei enthält.
            </para>
        </note>

        <para>
            <methodname>getMimeType()</methodname> gibt den Mimetyp einer Datei zurück. Wenn mehr
            als eine Datei hochgeladen wurde wird ein Array zurückgegeben, andernfalls ein String.
        </para>

        <example id="zend.file.transfer.introduction.informations.getmimetype">
            <title>Den Mimetyp einer Datei bekommen</title>

            <programlisting language="php"><![CDATA[
$upload = new Zend_File_Transfer();
$upload->receive();

$mime = $upload->getMimeType();

// Gibt den Mimetyp des 'foo' Form Elements zurück
$names = $upload->getMimeType('foo');
]]></programlisting>

        </example>

        <note>
            <title>Vom Client angegebener MimeTyp</title>

            <para>
                Es ist zu beachten das der MimeTyp welcher vom Client angegeben wird, nicht als
                sichere Eingabe betrachtet wird. Deswegen wird der echte MimeTyp der Datei erkannt
                und statt dem Mimetyp welcher vom Client geschickt wird, zurückgegeben.
            </para>
        </note>

        <warning>
            <title>Mögliche Exception</title>

            <para>
                Beachte das diese Methode die fileinfo Erweiterung verwendet wenn Sie vorhanden ist.
                Wenn diese Erweiterung nicht gefunden werden kann wird die mimemagic Erweiterung
                verwendet. Wenn keine Erweiterung gefunden wird dann wird eine Exception geworfen.
            </para>
        </warning>

        <warning>
            <title>Originale Daten in $_FILES</title>

            <para>
                Aus Sicherheitsgründen werden auch die originalen Daten in $_FILES überschrieben
                sobald <classname>Zend_File_Transfer</classname> initiiert wird. Wenn man dieses
                Verhalten unterdrücken will und die originalen Daten benötigt, kann bei der
                Instanzierung die Option <property>detectInfos</property> einfach auf
                <constant>FALSE</constant> gesetzt werden.
            </para>

            <para>
                Diese Option hat keinen Effekt nachdem <classname>Zend_File_Transfer</classname>
                instanziert wurde.
            </para>
        </warning>
    </sect2>

    <sect2 id="zend.file.transfer.introduction.uploadprogress">
        <title>Fortschritt für Datei Uploads</title>

        <para>
            <classname>Zend_File_Transfer</classname> kann den aktuellen Status eines gerade
            stattfindenden Datei Uploads erheben. Um dieses Feature zu verwenden muß man entweder
            die <acronym>APC</acronym> Erweiterung verwenden, die mit den meisten standardmäßigen
            <acronym>PHP</acronym> Installationen vorhanden ist, oder die
            <classname>UploadProgress</classname> Erweiterung. Beide Erweiterungen werden erkannt
            und automatisch verwendet. Um den Fortschritt zu erhalten muß man einige Voraussetzungen
            erfüllen.
        </para>

        <para>
            Erstens, muß man entweder <acronym>APC</acronym> oder
            <classname>UploadProgress</classname> aktiviert haben. Es ist zu beachten das dieses
            Feature von <acronym>APC</acronym> in der eigenen <filename>php.ini</filename>
            ausgeschaltet werden kann.
        </para>

        <para>
            Zweitens, muß man die richtigen unsichtbaren Felder im Formular hinzugefügt haben das
            die Dateien sendet. Wenn man <classname>Zend_Form_Element_File</classname> verwendet
            werden diese unsichtbaren Felder automatisch von <classname>Zend_Form</classname>
            hinzugefügt.
        </para>

        <para>
            Wenn die oberen zwei Punkte vorhanden sind dann ist man in der Lage den aktuellen
            Fortschritt des Datei uploads zu erhalten indem man die
            <methodname>getProgress()</methodname> Methode verwendet. Aktuell gibt es 2 offizielle
            Wege um das hand zu haben.
        </para>

        <sect3 id="zend.file.transfer.introduction.uploadprogress.progressadapter">
            <title>Verwenden eines Progressbar Adapters</title>

            <para>
                Man kann einen bequemen <emphasis>Zend_ProgressBar</emphasis> verwenden um den
                aktuellen Fortschritt zu erhalten und kann Ihn dann auf einfachem Wege dem Benutzer
                zeigen.
            </para>

            <para>
                Um das zu ermöglichen, muß man den gewünschten
                <emphasis>Zend_ProgressBar_Adapter</emphasis> bei
                <methodname>getProgress()</methodname> hinzufügen wenn es das erste Mal aufgerufen
                wird. Für Details über den zu verwendenden Adapter, bitte im Kapitel <link
                    linkend="zend.progressbar.adapters">Zend_ProgressBar Standard Adapters</link>
                nachsehen.
            </para>

            <example id="zend.file.transfer.introduction.uploadprogress.progressadapter.example1">
                <title>
                    Verwenden eines Progressbar Adapters um den aktuellen Status zu erhalten
                </title>

                <programlisting language="php"><![CDATA[
$adapter = new Zend_ProgressBar_Adapter_Console();
$upload  = Zend_File_Transfer_Adapter_Http::getProgress($adapter);

$upload = null;
while (!$upload['done']) {
    $upload = Zend_File_Transfer_Adapter_Http:getProgress($upload);
}
]]></programlisting>
            </example>

            <para>
                Die komplette Handhabung wird von <methodname>getProgress()</methodname> im
                Hintergrund durchgeführt.
            </para>
        </sect3>

        <sect3 id="zend.file.transfer.introduction.uploadprogress.manually">
            <title>getProgress() händisch verwenden</title>

            <para>
                Man kann mit <methodname>getProgress()</methodname> auch händisch arbeiten, also
                ohne die Verwendung von <classname>Zend_ProgressBar</classname>.
            </para>

            <para>
                <methodname>getProgress()</methodname> muß ohne Einstellungen aufgerufen werden. Es
                gibt anschließend ein Array mit verschiedenen Schlüssel zurück. Sie unterscheiden
                sich, abhängig von der verwendeten <acronym>PHP</acronym> Extension. Aber die
                folgenden Schlüssel werden unabhängig von der Extension zurück gegeben:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <emphasis>id</emphasis>: Die ID dieses Uploads. Die ID identifiziert den
                        Upload in der Extension. Man kann Sie auf den Wert des versteckten
                        Schlüssels setzen welcher den Upload identifiziert wenn
                        <methodname>getProgress()</methodname> das erste Mal aufgerufen wird.
                        Standardmäßig ist er auf <emphasis>progress_key</emphasis> gesetzt. Man
                        darf die ID nicht im Nachhinein ändern.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>total</emphasis>: Die komplette Größe der Datei die hochgeladen
                        wird in Bytes als Integer.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>current</emphasis>: Die aktuelle hochgeladene Größe der
                        Datei in Bytes als Integer.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>rate</emphasis>: Die durchschnittliche Geschwindigkeit des
                        Uploads in Bytes pro Sekunde als Integer.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>done</emphasis>: Gibt <constant>TRUE</constant> zurück wenn der
                        Upload abgeschlossen wurde, andernfalls <constant>FALSE</constant>.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>message</emphasis>: Die aktuelle Meldung. Entweder der
                        Fortschritt als Text in der Form <emphasis>10kB / 200kB</emphasis>, oder
                        eine hilfreiche Nachricht im Fall eines Problems. Probleme könnten sein,
                        das kein Upload durchgeführt wird, das ein Fehler während des Empfangens der
                        Daten, für den Fortschritt, aufgetreten ist, oder das der Upload abgebrochen
                        wurde.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>progress</emphasis>: Dieser optionale Schlüssel nimmt eine
                        Instanz von <classname>Zend_ProgressBar_Adapter</classname> oder
                        <classname>Zend_ProgressBar</classname>, und erlaubt es, den aktuellen
                        Status des Uploads, in einer Progressbar zu erhalten
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>session</emphasis>: Dieser optionale Schlüssel nimmt den Namen
                        eines Session Namespaces entgegen der in
                        <classname>Zend_ProgressBar</classname> verwendet wird. Wenn dieser
                        Schlüssel nicht angegeben wird, ist er standardmäßig
                        <classname>Zend_File_Transfer_Adapter_Http_ProgressBar</classname>.
                    </para>
                </listitem>
            </itemizedlist>

            <para>
                Alle anderen zurückgegebenen Schlüssel werden direkt von den Extensions übernommen
                und werden nicht geprüft.
            </para>

            <para>
                Das folgende Beispiel zeigt eine mögliche händische Verwendung:
            </para>

            <example id="zend.file.transfer.introduction.uploadprogress.manually.example1">
                <title>Händische Verwendung des Datei Fortschritts</title>

                <programlisting language="php"><![CDATA[
$upload  = Zend_File_Transfer_Adapter_Http::getProgress();

while (!$upload['done']) {
    $upload = Zend_File_Transfer_Adapter_Http:getProgress($upload);
    print "\nAktueller Fortschritt:".$upload['message'];
    // Tu was zu tun ist
}
]]></programlisting>
            </example>

            <note>
                <title>Die Datei kennen von welcher der Fortschritt kommen soll</title>

                <para>
                    Das obige Beispiel funktioniert wenn der identifizierte Upload auf
                    'progress_key' gesetzt wurde. Wenn man einen anderen Identifikator im Formular
                    verwendet muss man den verwendeten Identifikator als ersten Parameter an
                    <methodname>getProgress()</methodname> bei initialen Aufruf übergeben.
                </para>
            </note>
        </sect3>
    </sect2>
</sect1>
