PHP readfile() fügt der heruntergeladenen Datei zusätzliche Bytes hinzu

Lesezeit: 5 Minuten

Benutzer-Avatar
jimmyjambles

Ich versuche, ein Problem zu beheben, das ich beim Herunterladen einer “zip”-Datei aus einem PHP-Skript habe. Es scheint, dass, wenn ich die Datei mit dem folgenden Code herunterlade, die heruntergeladene Datei ein zusätzliches 0A09 an den Anfang der Datei angehängt hat, was dazu führt, dass Winzip einen Korruptionsfehler ausgibt.

<?php
$pagePermissions = 7;
require_once ('util/check.php');
require_once ('util/file_manager.php');

$file_manager = new FileManager();

if ($_SERVER['REQUEST_METHOD'] == "GET") {
if (isset($_GET['q']) && $_GET['q'] == 'logout') {
    //require_once ('util/users.php');
    //$userdata = new Userdata();
    $userdata -> kill_session();
    header("Location: download.php");
    exit ;
}

if (isset($_GET['q']) && $_GET['q'] == 'fetch') {
    if (isset($_GET['name'])) {
        @apache_setenv('no-gzip', 1); 
        header("Content-length: " . filesize('upload/' . $_GET['name'])); 
        header('Content-type: application/zip');
        //header("Content-Disposition: attachment; filename=\"{$_GET['name']}\" ");
        header("Content-Disposition: attachment; filename={$_GET['name']}");
        header('Content-Transfer-Encoding: binary');

        readfile('upload/' . $_GET['name']);
        exit();
    }
}

}
?>

Jede Hilfe wäre sehr willkommen, die Datei lädt problemlos über einen direkten Link herunter, die an den Anfang der Datei angehängten 2 Bytes treten nur durch diesen Code auf. Danke im Voraus

  • Ich hoffe, Sie verwenden das nicht in einer Produktionsumgebung, es ermöglicht einem Besucher das Abrufen irgendein Datei auf Ihrem Server, auf die PHP Zugriff hat.

    – igorw

    7. November 2011 um 19:40 Uhr

  • Hat nichts mit Ihrem Fehler zu tun, aber … filtern Sie Ihre Eingabe! Andernfalls kann ich ?name=../../../etc/passwd in der URL angeben.

    – Alex Howansky

    7. November 2011 um 19:41 Uhr

  • readfile() wird die Anzahl der aus der Datei gelesenen Bytes am Ende anhängen.

    – Satvik

    30. Juni 2021 um 13:27 Uhr

Benutzer-Avatar
Yanik Rochon

Entfernen Sie das letzte ?> und überprüfen Sie, ob sich Ihr Eröffnungs-Tag in der allerersten Zeile befindet, beim allerersten Zeichen Ihrer Skripte. PHP-Dateien unterlassen Sie müssen mit End-Tags enden. Der Grund, warum Ihre heruntergeladenen Dateien ein (oder mehr) \r\n liegt daran, dass PHP alles außerhalb von direkt echoen (ausgeben) wird <?php ?>. Wenn Ihr Skript HTML nicht wiedergibt, lassen Sie normalerweise das schließende PHP-Tag weg, da es nicht obligatorisch ist und meiner Meinung nach mehr Probleme verursacht als alles andere.

** Bearbeiten **

Wenn Sie das PHP-Handbuch für readfileSie haben ein nützliches Beispiel, so ziemlich den Code, den Sie in Ihrer Frage haben, weniger zwei Codezeilen:

@apache_setenv('no-gzip', 1); 
header("Content-length: " . filesize('upload/' . $_GET['name'])); 
header('Content-type: application/zip');
//header("Content-Disposition: attachment; filename=\"{$_GET['name']}\" ");
header("Content-Disposition: attachment; filename={$_GET['name']}");
header('Content-Transfer-Encoding: binary');

// add these two lines
ob_clean();   // discard any data in the output buffer (if possible)
flush();      // flush headers (if possible)

readfile('upload/' . $_GET['name']);
exit();

Wenn Sie danach immer noch ein Problem haben, liegt das Problem möglicherweise nicht an Ihrem PHP-Code.

  • Stellen Sie außerdem sicher, dass <?php wirklich steht am Anfang der ersten Zeile im Skript, mit nichts davor. Oh, und stellen Sie sicher, dass diese beiden Dinge auch für alle anderen PHP-Dateien gelten, die Sie einschließen.

    – Ilmari Karonen

    7. November 2011 um 19:53 Uhr


  • Es hört sich nach einem Problem mit Leerzeichen an, aber da die Readfile vor dem schließenden ?> Wäre Leerzeichen nach der Readfile wirklich das Problem? Zum Senden von Binärdateien bevorzuge ich X-Sendfile, wenn Sie Zugriff auf das benötigte Apache-Modul haben. Die Verwendung von x-sendfile erhöht auch die Sicherheit bei Problemen wie dem Fehlen von GET-Säuberungsaufrufen von Dateien außerhalb des Apache-Webstammverzeichnisses.

    – Alice Wunder

    7. November 2011 um 19:56 Uhr

  • ja. Die Funktion readfile gibt die Datei aus und kehrt dann zurück. Wenn nach den schließenden Tags am Ende des Skripts zusätzliche Zeichen stehen, wird alles wiederholt, bevor die HTTP-Verbindung geschlossen wird.

    – Yanik Rochon

    7. November 2011 um 20:04 Uhr

  • Aber in dieser Frage scheint das Problem vom öffnenden PHP-Tag seit dem Extra herzurühren \r\n steht am Anfang.

    – Yanik Rochon

    7. November 2011 um 20:06 Uhr

  • Genial, ob_clean(); tat es für mich.

    – Jakob Mouka

    31. März 2018 um 21:13 Uhr

Benutzer-Avatar
Raffiniert

Entschuldige die späte Antwort…..

Ich weiß nicht, ob ich Recht habe, bis Sie hier abstimmen. . . .

Bearbeiten Sie Ihren Code wie folgt:

ob_start(""); 
//instead of ob_start(); with out a null callback 

und

ob_end_clean();  //at the end , Note : "important" add instead of ob_end_flush()

dh;

ob_start("");
//header           
ob_end_clean();

Ich bin heute auf ein ähnliches Problem im Zusammenhang mit readfile() gestoßen. Es stellt sich heraus, dass in meiner php.ini-Datei die Ausgabekomprimierung aktiviert ist und das das Flash-Modul beim Versuch, die Datei abzurufen, durcheinander gebracht hat. (Ich denke, es konnte nicht damit umgehen.)

Alles, was ich tun musste, war die Komprimierung in der Datei php.ini auszuschalten:

zlib.output_compression = off

Oder alternativ in Ihrem Skript:

<?php ini_set('zlib.output_compression', 'Off'); ?> 

Ich möchte dies nur teilen, falls jemand anderes Probleme hatte, Dateien von einer readfile() -Ausgabe zu empfangen.

Ich hatte ein ähnliches Problem in Joomla (2.5), bei dem ich readfile verwendete, um Excel-Dateien (.xls) an den Benutzer zurückzugeben.

Ich habe auch bemerkt, dass die Text- und XML-Dateien am Anfang auch etwas Code eingefügt hatten, aber ich habe es fast ignoriert, weil XML- und Text-Reader dazu neigten, die Dateien immer noch zu öffnen.

Ich habe mich entschieden, Yanicks Vorschläge auszuprobieren (anstatt mit Serverkomprimierungsoptionen zu spielen), indem ich einfach den Puffer vor der Readfile geleert habe:

ob_clean();   // discard any data in the output buffer (if possible)
flush();      // flush headers (if possible)

Puh, es hat funktioniert. Ich schlage dies als alternative Antwort vor: Um die Grundursache hervorzuheben, zu zeigen, dass es ein Joomla-Problem beheben kann, und weil ich eine Mischung aus Binär- und Textrückgaben hatte.

Nur um hinzuzufügen (Entschuldigung, wenn dies offensichtlich ist!) – die Mime-Typ-Einstellung hat gut funktioniert:

$document = JFactory::getDocument();
$document->setMimeEncoding($mimetype);

Ich musste nicht einmal „Content-Transfer-Encoding: binary“ einstellen, wenn der Mime-Typ „application/octet-stream“ war.

Ich hatte das gleiche Problem, also habe ich diese Header verwendet und meine Lösung bekommen.

    $filename = ABSPATH.'/wp-content/summary/user_content/'.trim($file);
    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Content-Description: File Transfer');
    header('Content-Type: text/text');
    header('Content-Disposition: attachment; filename="'.$file.'"');
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: max-age=0');
    readfile($filename);
    exit;

Benutzer-Avatar
Michael Chaplin

Ich hatte ein ähnliches Problem mit Leerzeichen am Anfang einer Bilddatei.

Ich vermute, dass mein Problem durch Leerzeichen vor dem Öffnen verursacht wurde

Was für mich funktionierte, war:

@ob_start('');  //@ supresses a warning  
//header entries
ob_end_clean();
ob_clean();
readfile($file);

1015030cookie-checkPHP readfile() fügt der heruntergeladenen Datei zusätzliche Bytes hinzu

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy