Ankündigung

Einklappen
Keine Ankündigung bisher.

php download bricht immer ab

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • php download bricht immer ab

    Hallo Zusammen

    habe ein Script mit dem ich PHP Download Links erzeuge

    ich weis das readfile() immer probleme mit großen files hat

    hab schon mehrere versionen versucht, alle brechen immer irgendwo mitten drin ca. ab

    ich bin am verzweifeln

    brauche dringend eine lösung mit der ich dateien 200mb - 1GB ca. downloaden kann

    Danke


    Version 1:
    PHP-Code:
        public static function processDownload($filePath$filename)
        {
            
    jimport('joomla.filesystem.file');
            
    $fsize = @filesize($filePath);
            
    $mod_date date('r'filemtime($filePath));
            
    $cont_dis 'attachment';
            
    $ext JFile::getExt($filename);
            
    $mime DMSHelper::getMimeType($ext);
            
    // required for IE, otherwise Content-disposition is ignored
            
    if (ini_get('zlib.output_compression'))
            {
                
    ini_set('zlib.output_compression''Off');
            }
            
    header("Pragma: public");
            
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            
    header("Expires: 0");
            
    header("Content-Transfer-Encoding: binary");
            
    header('Content-Disposition:' $cont_dis ';' ' filename="' JFile::getName($filename) . '";' ' modification-date="' $mod_date '";' ' size=' $fsize ';'); //RFC2183
            
    header("Content-Type: " $mime); // MIME type
            
    header("Content-Length: " $fsize);
            
            if (!
    ini_get('safe_mode'))
            { 
    // set_time_limit doesn't work in safe mode
                
    @set_time_limit(0);
            }
            
    DMSHelper::readfile_chunked($filePath);
        }

        public static function 
    readfile_chunked($filename$retbytes true)
        {
            
    $chunksize * (1024 1024); // how many bytes per chunk
            
    $buffer '';
            
    $cnt 0;
            
    $handle fopen($filename'rb');
            if (
    $handle === false)
            {
                return 
    false;
            }
            while (!
    feof($handle))
            {
                
    $buffer fread($handle$chunksize);
                echo 
    $buffer;
                @
    ob_flush();
                
    flush();
                if (
    $retbytes)
                {
                    
    $cnt += strlen($buffer);
                }
            }
            
    $status fclose($handle);
            if (
    $retbytes && $status)
            {
                return 
    $cnt// return num. bytes delivered like readfile() does.
            
    }
            return 
    $status;
        } 
    Version 2:
    PHP-Code:
        public static function processDownload($filePath$filename)
        {
            
    set_time_limit(0);
            
    ini_set('memory_limit''512M');
            
    jimport('joomla.filesystem.file');
            if(!empty(
    $filePath))
            {
                
    $fileName                  JFile::getName($filename);
                
    $fileExtnesion            JFile::getExt($filename);
                
    $contentType             DMSHelper::getMimeType($fileExtnesion);
                if(
    file_exists($filePath))
                {
                    
    $size     = @filesize($filePath);
                    
    $offset 0;
                    
    $length $size;
                    
    //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                    
    if(isset($_SERVER['HTTP_RANGE']))
                    {
                        
    preg_match('/bytes=(\d+)-(\d+)?/'$_SERVER['HTTP_RANGE'], $matches);
                        
    $offset intval($matches[1]);
                        
    $length intval($matches[2]) - $offset;
                        
    $fhandle fopen($filePath'r');
                        
    fseek($fhandle$offset); // seek to the requested offset, this is 0 if it's not a partial content request
                        
    $data fread($fhandle$length);
                        
    fclose($fhandle);
                        
    header('HTTP/1.1 206 Partial Content');
                        
    header('Content-Range: bytes ' $offset '-' . ($offset $length) . '/' $size);
                    }
    //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                    //USUAL HEADERS FOR DOWNLOAD
                    
    header("Content-Disposition: attachment;filename=".$fileName);
                    
    header('Content-Type: '.$contentType);
                    
    header("Accept-Ranges: bytes");
                    
    header("Pragma: public");
                    
    header("Expires: -1");
                    
    header("Cache-Control: no-cache");
                    
    header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
                    
    header("Content-Length: ".@filesize($filePath));
                    
    $chunksize 10 * (1024 1024); //10MB (highest possible fread length)
                    
    if ($size $chunksize)
                    {
                      
    $handle fopen($filePath'rb');
                      
    $buffer '';
                      while (!
    feof($handle) && (connection_status() === CONNECTION_NORMAL)) 
                      {
                        
    $buffer fread($handle$chunksize);
                        print 
    $buffer;
                        
    ob_flush();
                        
    flush(); 
                      }
                      if(
    connection_status() !== CONNECTION_NORMAL)
                      {
                        echo 
    "Connection aborted";
                      }
                      
    fclose($handle);
                    }
                    else 
                    {
                      
    ob_clean();
                      
    flush();
                      
    readfile($filePath);
                    }
                 }
                 else
                 {
                   echo 
    'File does not exist!';
                 }
            }
            else
            {
                echo 
    'There is no file to download!';
            }
        } 

  • #2
    @ob_flush();
    Wat soll dat werden?

    Ohne das @ erscheint da eine Notice (weil ohne ob_start() gibt es keinen Outputbuffer zum flushen)

    Überhaupt ist die Benutzung des Fehlerunterdrückungsoperators beim Debugging ein "Fail!"

    hab schon mehrere versionen versucht, alle brechen immer irgendwo mitten drin ca. ab
    Das heisst? Immer an der gleichen Byteposition? Immer zur gleichen Zeit?
    Wurde das time_limit erfolgreich abgeschaltet (so was sieht man von hier aus nicht)?
    Wie sieht das System aus, sitzt dein Webserver hinter einem Loadbalancer? Was sagen die Logfiles zum Abbruch?
    Welche Debuggingversuche hast du schon selber übernommen, mit welchem Ergebnis?
    Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

    Kommentar


    • #3
      moin

      kennen mich darmit leider garnicht so gut aus

      version 1 habe ich aus dem joomla addon DMS (document seller)

      da diese nicht funktioniert habe ich über google version 2 probiert

      leider funktionieren eben beide nicht

      Server ist ein alfahosting webserver XXL Paket mit mehrere domains

      einstellungen dort kann ich nicht ändern
      ich häng die einstellungen mal als anhang bei

      das mit ob_start() musste mir mal genauer erklären, weil hab da echt 0 ahnung von

      hier nochmal der ausschnitt wie es derzeit live ist

      download einer 780 mb datei brict immer unterschiedlich ab
      mal 350 mb
      mal 450 mb
      mal 200 mb
      mal 513 mb

      der läd das video einfach nicht ganz runter, und dann von 11 minuten sind eben nur 4-9 ca. je nach download eben verfügbar


      PHP-Code:
      public static function processDownload($filePath$filename)
          {
              
      set_time_limit(0);
              
      ini_set('memory_limit''512M');
              
      jimport('joomla.filesystem.file');
              if(!empty(
      $filePath))
              {
                  
      $fileName                  JFile::getName($filename);
                  
      $fileExtnesion            JFile::getExt($filename);
                  
      $contentType             DMSHelper::getMimeType($fileExtnesion);
                  if(
      file_exists($filePath))
                  {
                      
      $size     = @filesize($filePath);
                      
      $offset 0;
                      
      $length $size;
                      
      //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                      
      if(isset($_SERVER['HTTP_RANGE']))
                      {
                          
      preg_match('/bytes=(\d+)-(\d+)?/'$_SERVER['HTTP_RANGE'], $matches);
                          
      $offset intval($matches[1]);
                          
      $length intval($matches[2]) - $offset;
                          
      $fhandle fopen($filePath'r');
                          
      fseek($fhandle$offset); // seek to the requested offset, this is 0 if it's not a partial content request
                          
      $data fread($fhandle$length);
                          
      fclose($fhandle);
                          
      header('HTTP/1.1 206 Partial Content');
                          
      header('Content-Range: bytes ' $offset '-' . ($offset $length) . '/' $size);
                      }
      //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                      //USUAL HEADERS FOR DOWNLOAD
                      
      header("Content-Disposition: attachment;filename=".$fileName);
                      
      header('Content-Type: '.$contentType);
                      
      header("Accept-Ranges: bytes");
                      
      header("Pragma: public");
                      
      header("Expires: -1");
                      
      header("Cache-Control: no-cache");
                      
      header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
                      
      header("Content-Length: ".@filesize($filePath));
                      
      $chunksize 10 * (1024 1024); //10MB (highest possible fread length)
                      
      if ($size $chunksize)
                      {
                        
      $handle fopen($filePath'rb');
                        
      $buffer '';
                        while (!
      feof($handle) && (connection_status() === CONNECTION_NORMAL)) 
                        {
                          
      $buffer fread($handle$chunksize);
                          print 
      $buffer;
                          
      ob_flush();
                          
      flush(); 
                        }
                        if(
      connection_status() !== CONNECTION_NORMAL)
                        {
                          echo 
      "Connection aborted";
                        }
                        
      fclose($handle);
                      }
                      else 
                      {
                        
      ob_clean();
                        
      flush();
                        
      readfile($filePath);
                      }
                   }
                   else
                   {
                     echo 
      'File does not exist!';
                   }
              }
              else
              {
                  echo 
      'There is no file to download!';
              }
          } 
      Angehängte Dateien

      Kommentar


      • #4
        Andere Frage, wieso musst du den Download über PHP schienen?
        [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

        Kommentar


        • #5
          naja das ist ein modul das documents verkauft in joomla
          da ist halt hinterlegt max downloads und days downloadlink expire und so ein spaß
          und man soll die videos ja nicht downloaden können einfach so
          sondern nur wer so ein link per mail (nach dem zahlungseingang) erhalten hat eben
          die meinten das muss per php sein

          aber muss ja auch mit php funktionieren irgendwie

          Kommentar


          • #6
            Dann solltest du vielleicht einmal "die" Fragen. Wir haben jedenfalls keine grosse Lust, dein Produkt zu supporten.
            [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

            Kommentar


            • #7
              naja "die" haben gesagt das soll so tun
              und ich verlange ja nicht das jemand was supporten soll
              wollte nur fragen ob sich wer damit auskennt was an dem zuletzt gepostetem code wohl nicht stimmen könnte bzw. warum es nicht geht
              ist doch hier ein php fragetread oder ? oder ist fragen mitlerweile verboten

              grüße

              Kommentar


              • #8
                Wenn in den Logfiles überhaupt nichts auftaucht, was auf ein Problem schliessen lässt, kontrollier mal die Webservereinstellungen hinsichtlich des idle-timeouts.

                Es kann vorkommen, das bei einem niedrigen timeout und einem kurzen "Hänger" in der Leitung der Webserver annimmt, das keine weiteren Daten mehr über die Leitung fliessen und kurzerhand die Verbindung kappt.

                Ich würde auch die Chunkgröße verkleinern... 10MB auf einmal ist ziemlich viel, handelsüblich sind Chunkgrößen von 4-32 KB.

                Und schmeiß die ob_* Funktionen raus, du brauchst kein Outputbuffering, vor allem nicht wenn du es falsch einsetzt.
                Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                Kommentar


                • #9
                  sowas wie eine timeout einstellung kann ich in der administrationsseite meines webserveranbieters nicht sehen bzw. ändern

                  also ob_flush(); und ob_clean(); rauswerfen, chunkk auf sagen wir mal
                  $chunksize = 1 * (1024 * 1024); ändern

                  werd ich gleich mal versuchen

                  Kommentar


                  • #10
                    geht leider immenrohc nicht

                    er öffnet den download, sagt erfolgreich es sind 731 mb downzuloaden und das es ne mp4 ist und alles sieht gut aus

                    ich starte den download

                    bei 421mb sagt der download fertig

                    und video geht statt 11 min nur 6...

                    hier der code

                    PHP-Code:
                    public static function processDownload($filePath$filename)
                        {
                            
                    set_time_limit(0);
                            
                    ini_set('memory_limit''512M');
                            
                    jimport('joomla.filesystem.file');
                            if(!empty(
                    $filePath))
                            {
                                
                    $fileName                  JFile::getName($filename);
                                
                    $fileExtnesion            JFile::getExt($filename);
                                
                    $contentType             DMSHelper::getMimeType($fileExtnesion);
                                if(
                    file_exists($filePath))
                                {
                                    
                    $size     = @filesize($filePath);
                                    
                    $offset 0;
                                    
                    $length $size;
                                    
                    //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                                    
                    if(isset($_SERVER['HTTP_RANGE']))
                                    {
                                        
                    preg_match('/bytes=(\d+)-(\d+)?/'$_SERVER['HTTP_RANGE'], $matches);
                                        
                    $offset intval($matches[1]);
                                        
                    $length intval($matches[2]) - $offset;
                                        
                    $fhandle fopen($filePath'r');
                                        
                    fseek($fhandle$offset); // seek to the requested offset, this is 0 if it's not a partial content request
                                        
                    $data fread($fhandle$length);
                                        
                    fclose($fhandle);
                                        
                    header('HTTP/1.1 206 Partial Content');
                                        
                    header('Content-Range: bytes ' $offset '-' . ($offset $length) . '/' $size);
                                    }
                    //HEADERS FOR PARTIAL DOWNLOAD FACILITY BEGINS
                                    //USUAL HEADERS FOR DOWNLOAD
                                    
                    header("Content-Disposition: attachment;filename=".$fileName);
                                    
                    header('Content-Type: '.$contentType);
                                    
                    header("Accept-Ranges: bytes");
                                    
                    header("Pragma: public");
                                    
                    header("Expires: -1");
                                    
                    header("Cache-Control: no-cache");
                                    
                    header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
                                    
                    header("Content-Length: ".@filesize($filePath));
                                    
                    $chunksize * (1024 1024); //10MB (highest possible fread length)
                                    
                    if ($size $chunksize)
                                    {
                                      
                    $handle fopen($filePath'rb');
                                      
                    $buffer '';
                                      while (!
                    feof($handle) && (connection_status() === CONNECTION_NORMAL)) 
                                      {
                                        
                    $buffer fread($handle$chunksize);
                                        print 
                    $buffer;
                                        
                    flush();
                                      }
                                      if(
                    connection_status() !== CONNECTION_NORMAL)
                                      {
                                        echo 
                    "Connection aborted";
                                      }
                                      
                    fclose($handle);
                                    }
                                    else 
                                    {
                                      
                    flush();
                                      
                    readfile($filePath);
                                    }
                                 }
                                 else
                                 {
                                   echo 
                    'File does not exist!';
                                 }
                            }
                            else
                            {
                                echo 
                    'There is no file to download!';
                            }
                        } 

                    Kommentar


                    • #11
                      hab mir nun nohcmal von ner anderen seite ne "Lösung" runtergeladen und reingemacht

                      funktioniert im endeffekt auch sehr gut (und einfacher zu lesen behaupte ich mal)
                      also für mich zumindest

                      download wird aber ebenfalls nicht komplett geladen

                      woran kann das denn liegen, am code liegt das doch wohl nicht oder, welche servereinstellungen muss ich da checken lassen alle
                      dann schreib ich meinem provider sonst mal

                      PHP-Code:
                      public static function processDownload($filePath$filename)
                          {
                              
                      ob_end_clean();
                              if (!
                      is_file($filePath) or connection_status()!=0) return(FALSE);
                              
                      header("Cache-Control: no-store, no-cache, must-revalidate");
                              
                      header("Cache-Control: post-check=0, pre-check=0"false);
                              
                      header("Pragma: no-cache");
                              
                      header("Expires: ".gmdate("D, d M Y H:i:s"mktime(date("H")+2date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
                              
                      header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
                              
                      header("Content-Type: ".DMSHelper::getMimeType(JFile::getExt($filename)));
                              
                      header("Content-Length: ".(string)(filesize($filePath)));
                              
                      header("Content-Disposition: attachment;filename=".JFile::getName($filename));
                              
                      header("Content-Transfer-Encoding: binary\n");
                              if (
                      $file fopen($filePath'rb')) {
                                  while(!
                      feof($file) and (connection_status()==0)) {
                                      print(
                      fread($file1024*8));
                                      
                      flush();
                              }
                              
                      fclose($file);
                              }
                          } 
                      oder kann es sein das der bei

                      while(!feof($file) and (connection_status()==0)) {

                      da irgendwie vorzeitig denkt er seie bei end of file ??
                      aber dann wäre es wohl nicht jedes mal unterschiedlich ? oder ?

                      Kommentar


                      • #12
                        Protokollier doch mal mit, insbesondere Größenangaben (Anzahl Bytes gesendent, Bytes übrig, Ranges usw.), mit jedem Schleifendurchlauf.

                        Und überprüf mal, ob tatsächlich HTTP_RANGE verwendet wird (das sieht mir nämlich nicht richtig aus, was du da machst... du akzeptierst die Range, liest auch die Daten aus der Datei, sendest sie aber nicht!)
                        Diesen Teil würde ich mal auskommentieren und dann nochmal testen...
                        Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                        Kommentar


                        • #13
                          hi
                          wie kann ich denn protocollieren ?
                          bin php noch nicht so gut


                          und ob HTTP_RANGE verwendet wird ehh das sagt mir grade nix
                          der letzte part an quellcode den ich nutze ist ja wesentlich schmaler
                          funzt aber leider eben auch nicht

                          Kommentar


                          • #14
                            Protokoll = Log Datei (selber schreiben)

                            Es scheint mir auch eher ein Problem am Server zu sein und nicht am Code (der ist so minimalistisch, es wäre schwer einen solchen Fehler da drin zu verstecken). Bis auf den Part mit connection_status() ist das die kleinste, denkbare Streamingschleife.
                            Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                            Kommentar


                            • #15
                              ja mir scheint auch bei dem kleinen code kann nicht mehr großartig falsch sein

                              wlche servereinstellungen sind denn hierzu wichtig bzw sollten eingestellt sein ??

                              grüße

                              Kommentar

                              Lädt...
                              X