PHP: viele Bilder mit einem Klick herunterladen

simusch

simusch

Aktives Mitglied
Thread Starter
Dabei seit
27.09.2004
Beiträge
2.030
Reaktionspunkte
219
Hallo zusammen

Ich stehe vor einem Problem:

Ich möchte durch Klick auf einen Button (in einer Fotogalerie) alle angezeigten Bilder herunterladen lassen.
Ich habe bereits versucht, die Bilder in ein ZIP verpacken zu lassen und dann zu laden - Dies funktioniert auch problemlos bis ca. 25-30 Bilder (je 3-5MB).
Doch bei >30 Bilder passiert einfach gar nichts.

Gibt es eine einfache Möglichkeit, die Downloads gestaffelt zu starten und einzelne Bilder herunterladen zu lassen?


Bestehende Zip-Variante:

PHP:
    require "interface/zip.class.php"; // Get the zipfile class 
    
    //create zip-file
    $zipfile = new zipfile;
    $zipfile->create_dir(".");
                
    //Bilder aus DB auslesen (Abfrage entfernt)
    while($feld = @mysql_fetch_array($erg))
    {
        $zipfile->create_file(file_get_contents("pfad/zum/bild.jpg"), "dateiname_in_zipfile.jpg");
    }

    //File ausgeben
    header("Content-type: application/zip"); 
    header("Content-disposition: attachment;filename=\"test.zip\""); 
    echo $zipfile->zipped_file();
 
Ich kann es auf die Schnelle nicht ausprobieren, aber so in etwa müsste es klappen, damit alle Bilder der Reihe nach heruntergeladen werden. Wichtig ist das session_write_close(), damit der Download zum Hintergrundprozess wird.
PHP:
<?php
	// Bildauswahl (z.B über Selectboxes, Datenbank etc.) Demo in Form eines assoziativen Arrays
	
	$bilder = array ('/pfad/bild1.jpg' => 'bildname1', '/pfad/bild2.jpg' => 'bildname2', ...);
	
	$disposition = 'attachment';

	// irgendein Mime-Type, der den Downlod erzwingt 
	// application/octet-stream funktioniert nicht browserübergreifend
	
	$mime  = 'application/downloadfile'; // dafür wirst du gesteinigt			

	session_write_close(); // dann klappt's auch mit den Nachbarn
	
	if (count ($bilder))
	{
		foreach ($bilder as $key => $val)
		{
			$fp = @fopen ($key, 'r');
			 
			header ('Pragma: ');
			header ('Cache-Control: ');
		
			if (isset ($_SERVER['HTTPS'])) 
			{
				// wegen IE in HTTPS mode
				
				header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
				header ('Last-Modified: '.gmdate ('D, d M Y H:i:s').' GMT');
				header ('Cache-Control: no-store, no-cache, must-revalidate'); 
				header ('Cache-Control: post-check=0, pre-check=0', false);
			}
			else if ($disposition == 'attachment') 
			{
				header ('Expires: 0');
			}
		
			header ('Content-Type: '.$mime);
			header ('Content-Disposition:'.$disposition.'; filename="'.trim (htmlentities ($val)).'"');
			header ('Content-Description: '.trim (htmlentities ($val)));
			header ('Content-Length: '.(string)(filesize ($key)));
			
			@fpassthru ($fp);	
		}
		
		exit;
	}
?>
 
danke für den Tipp :)

Mir wird immer nur das erste Bild geladen (habe das Script natürlich ein bisschen angepasst...)

PHP:
                    $disposition = 'attachment'; 
                
                    // irgendein Mime-Type, der den Downlod erzwingt  
                    // application/octet-stream funktioniert nicht browserübergreifend 

                    $mime  = 'application/downloadfile'; // dafür wirst du gesteinigt             
                
                    session_write_close(); // dann klappt's auch mit den Nachbarn 


                    while($feld = @mysql_fetch_array($erg))
                    {
                        if(album_check($_SESSION[group_id],$feld[album_id]))
                        {
                            $file = $feld[original];
                            $filename = eregi_replace(' ','_',$feld[name])."__by_".eregi_replace(' ','_',$feld[photographer])."__".eregi_replace(' ','_',$feld[title]);
                            
                            //datei einlesen
                            $fp = @fopen ($file, 'r');
                              
                            header ('Pragma: ');
                            header ('Cache-Control: ');
                         
                            if(isset($_SERVER['HTTPS']))
                            {
                                // wegen IE in HTTPS mode
                                 
                                //header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
                                header ('Last-Modified: '.gmdate ('D, d M Y H:i:s').' GMT');
                                header ('Cache-Control: no-store, no-cache, must-revalidate');
                                header ('Cache-Control: post-check=0, pre-check=0', false);
                            }
                            elseif($disposition == 'attachment')
                            { 
                                header ('Expires: 0');
                            }
                         
                            header ('Content-Type: '.$mime);
                            header ('Content-Disposition:'.$disposition.'; filename="'.trim(htmlentities($filename)).'"');
                            header ('Content-Description: '.trim(htmlentities($filename)));
                            header ('Content-Length: '.(string)(filesize ($file)));
                             
                            @fpassthru ($fp);
                        }
                        else
                        {
                            $error = 1;
                        }
                    }
 
Stimmt leider, war ein Denkfehler, die Schleife kann nicht funktionieren.
 
wenns eine große Zip werden soll, kommst an Fummlereien in der php.ini nicht rum.
 
Eine schmutzige Lösung gibts aber: Datei multidl.php
PHP:
<div style="height:0;width:0">
<?php
	$bilder = array ('./IM006222.JPG' => 'bildname1.jpg', './IM006223.JPG' => 'bildname2.jpg');
	foreach ($bilder as $key => $val)  
	print '<iframe src="dl.php?path='.$key.'&amp;pict='.$val.'"></iframe>';
?>
</div>
Datei dl.php
PHP:
<?php
	$disposition = 'attachment';

	// irgendein Mime-Type, der den Downlod erzwingt 
	// application/octet-stream funktioniert nicht browserübergreifend
	
	$mime  = 'application/downloadfile'; // dafür wirst du gesteinigt			

	if ($fp = @fopen ($_GET['path'], 'r'))
	{ 
		session_write_close(); // dann klappt's auch mit den Nachbarn
		
		header ('Pragma: ');
		header ('Cache-Control: ');

		if (isset ($_SERVER['HTTPS'])) 
		{
			// wegen IE in HTTPS mode
			
			header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
			header ('Last-Modified: '.gmdate ('D, d M Y H:i:s').' GMT');
			header ('Cache-Control: no-store, no-cache, must-revalidate'); 
			header ('Cache-Control: post-check=0, pre-check=0', false);
		}
		else if ($disposition == 'attachment') 
		{
			header ('Expires: 0');
		}
	
		header ('Content-Type: '.$mime);
		header ('Content-Disposition:'.$disposition.'; filename="'.trim (htmlentities ($_GET['pict'])).'"');
		header ('Content-Description: '.trim (htmlentities ($_GET['pict'])));
		header ('Content-Length: '.(string)(filesize ($_GET['path'])));
		
		@fpassthru ($fp);			
	}
	
	exit;
?>
EDIT: Das Schmutzige daran ist: der Download wird in HTML festgeschrieben - ein Pagereload startet ihn erneut.
PHP:
<?php header ('refresh: 0 / * oder 1 * /; url=(backpage)'); ?>
am Anfang der multidl.php ginge, oder am Ende ein
Code:
<script type="text/javascript">location.replace("backpage")</script>
oder noch besser: mit einer Session kontrolieren, ob die Seite schon mal aufgerufen wurde ...
 
Zuletzt bearbeitet:
simusch schrieb:
Doch bei >30 Bilder passiert einfach gar nichts.

ich denke wenn man das mal versucht zu präzisieren würde man die Ursache des Problemes finden und sich somit das gescripte hier sparen können!

In Zeiten von DSL sind doch einige 100GB kein Problem! Wir schieben in der Firma via PHP mehrfach täglich bis zu 300MB-Pakete durchs web ( sowohl up- als auch download).

Hast Du schonmal geprüft ob Dir das hier:

http://de2.php.net/set_time_limit

zum Verhängnis wird?
 
am time limit sollte es nicht liegen...

denn das download-script rödelt auch 10 minuten weiter, ohne etwas zu tun... ausser den Server zu belasten ;)

ich werds aber mal mit der iframe-methode versuchen... danke soweit!

simu
 
Zurück
Oben Unten