PHP - Chunk basiertes Herunterladen?



  • Hallo,
    folgende Situation:
    Ich möchte von einem fremden Server eine Datei, auf meinen eigenen Server herunterladen. Diese Datei(en) ist oftmals >1GB - 1,5GB groß.

    Meine Ideen:
    -Das File einfach per a-href von dem fremden Server über den lokalen Browser herunterladen und wieder auf eigenen Server hochladen -> Upload muss chunkbasierend zerstückelt werden, blöder Umweg und mehr Zeit Inanspruchnahme, weil erst gedownloadet und dann wieder geuploadet werden muss.

    -Die Datei direkt per PHP chunkbasiert "kopieren" (herunterladen).
    Beispiel: Lese ersten 16 Byte -> Erstelle neue Datei auf meinem Server -> Speichere Offset in Variable -> Schliesse erstes Dateihandle -> Öffne wieder Datei an Offset 16 -> Lese erneut die nächsten 16 Byte -> usw.

    Nun, wie geht man an solche Sachen ran? Ich bin nicht der beste in PHP, habe jedoch bereits von diesen PHP-Sockets und den Streams gehört. Wie sollte man das am Besten machen? Die beste Methode, für meine Verhältnisse, wäre die Zweite. Allerdings würden da in PHP tausende von Dateihandles erzeugt, dann wieder gelöscht, dann wieder erzeugt, dann wieder gelöscht etc. werden.

    Danke für eure Hilfe! P.S.: CURL wäre auch eine Möglichkeit, verwende ich allerdings eher ungerne.



  • wget
    GET
    lwp-download
    fetch
    ...



  • Grüß dich,
    danke für deine Antwort erstmal!

    Nun, so ganz verstehe ich nicht was du mir sagen möchtest. Ich habe mich nach deinen Sachen da erkundigt, aber wie gesagt, mir fehlt die große Ahnung von sowas. Könntest du die kurz erläutern?

    Im Grunde erübrigen sich folgende Probleme:
    -Das Skript sollte auf einem shared Hosting laufen, sprich es gibt festgelete Kapazitäten (upload/download)
    -Die Datei sollte nicht in den RAM (durch den Browser) geladen werden (außer eben immer kleine Parts)

    Auf stackoverflow habe ich folgenden Code gefunden:

    /**
     * Copy remote file over HTTP one small chunk at a time.
     *
     * @param $infile The full URL to the remote file
     * @param $outfile The path where to save the file
     */
    function copyfile_chunked($infile, $outfile) {
        $chunksize = 10 * (1024 * 1024); // 10 Megs
    
        /**
         * parse_url breaks a part a URL into it's parts, i.e. host, path,
         * query string, etc.
         */
        $parts = parse_url($infile);
        $i_handle = fsockopen($parts['host'], 80, $errstr, $errcode, 5);
        $o_handle = fopen($outfile, 'wb');
    
        if ($i_handle == false || $o_handle == false) {
            return false;
        }
    
        if (!empty($parts['query'])) {
            $parts['path'] .= '?' . $parts['query'];
        }
    
        /**
         * Send the request to the server for the file
         */
        $request = "GET {$parts['path']} HTTP/1.1\r\n";
        $request .= "Host: {$parts['host']}\r\n";
        $request .= "User-Agent: Mozilla/5.0\r\n";
        $request .= "Keep-Alive: 115\r\n";
        $request .= "Connection: keep-alive\r\n\r\n";
        fwrite($i_handle, $request);
    
        /**
         * Now read the headers from the remote server. We'll need
         * to get the content length.
         */
        $headers = array();
        while(!feof($i_handle)) {
            $line = fgets($i_handle);
            if ($line == "\r\n") break;
            $headers[] = $line;
        }
    
        /**
         * Look for the Content-Length header, and get the size
         * of the remote file.
         */
        $length = 0;
        foreach($headers as $header) {
            if (stripos($header, 'Content-Length:') === 0) {
                $length = (int)str_replace('Content-Length: ', '', $header);
                break;
            }
        }
    
        /**
         * Start reading in the remote file, and writing it to the
         * local file one chunk at a time.
         */
        $cnt = 0;
        while(!feof($i_handle)) {
            $buf = '';
            $buf = fread($i_handle, $chunksize);
            $bytes = fwrite($o_handle, $buf);
            if ($bytes == false) {
                return false;
            }
            $cnt += $bytes;
    
            /**
             * We're done reading when we've reached the conent length
             */
            if ($cnt >= $length) break;
        }
    
        fclose($i_handle);
        fclose($o_handle);
        return $cnt;
    }
    

    Schaut ja relativ kompakt aus. Der Coder davon meint es würde ne Datei in Chunks runterladen. Stimmt das?



  • Ich glaub, er meint das ganze dem OS des servers zu überlassen. spricht du kannst bspw. mit php befehle in der linux command line ausführen lassen.

    glaube "shell_exec()" ist der php befehl ( http://php.net/manual/en/function.shell-exec.php )

    EOPs beispiel sind dann wohl die passenden shell befehle für einen linux server.



  • Sind zwar keine shell-Befehle, aber das war schon meine Idee: Wieso das Rad neu erfinden wollen?
    wget und/oder curl sind eigentlich fast auf jedem server verfügbar. fetch ist für FreeBSD.

    "There's more than one way to skin a cat."


Anmelden zum Antworten