Voor een filemanagement heb ik een aantal checkboxen die elk hun eigen value hebben. Deze value is het pad naar het bestand.
Via een anker roep ik de jquery ajax aan die vervolgesn het php script aanroept.



<a href="#download" class="cb_down" title="Download">Download</a>

//  AJAX for Checkbox download		
$(document).on('click' , '.cb_down' , function() { 	
	
          var checkboxes_down = []; 
						
           $('.rafcheckbox').each(function() {   
		if(this.checked) {				
                checkboxes_down.push($(this).val()); 				     	
           }  
        });  
        checkboxes_down = checkboxes_down.toString(); 
		   		   
        $.ajax({  
                url:"", 								
                method:"POST",  
				
                data:{ checkboxes_down:checkboxes_down },  
                success:function(response){ 
														
			// geen response nodig
										
                } 
			
        });  
});


De php:


// Multiple download (checkboxes)
if(isset($_POST["checkboxes_down"])) { 

	// create a tmp folder for the zip file
	$tmpfolder = $MainFolderName.'/tmp';
	if (!is_dir($tmpfolder)) {
		 mkdir($tmpfolder, 0755, true);
	}

	$checkboxfiles = explode("," , $_POST["checkboxes_down"]); 
        $filename = "archive.zip";
	$filepath = $tmpfolder."/";
			
    foreach($checkboxfiles as $checkboxfile) {	
			
	Zip($checkboxfile, $tmpfolder."/archive.zip");	// "Zip" is functie die archive.zip file maakt						
	}

        if(file_exists($tmpfolder.'/archive.zip')){
						
								
		// http headers for zip downloads
		header("Pragma: public");
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: public");
		header("Content-Description: File Transfer");
		header("Content-type: application/octet-stream");
			
		header("Content-Disposition: attachment; filename=\"".$filename."\"");
		header("Content-Transfer-Encoding: binary");
		header("Content-Length: ". filesize($filepath.$filename));
						
		while (ob_get_level()) {
			ob_end_clean();
		}
		readfile($filepath.$filename);
		unlink($tmpfolder.'/archive.zip'); // unlink archive.zip			
		rmdir($tmpfolder); // remove tmpdir

		exit;
		
	}
}


Als ik een aantal checkboxen aanvink en op Download klik, wordt de archive.zip gemaakt met alle bestanden erin. Ik heb dit gechecked en dit werkt goed!
Alleen: readfile($filepath.$filename); werkt niet.
Ik heb geen idee waarom ik de .zip niet als download gepresenteerd krijg...
ik ga hier eens naar kijken. Dankjewel voor reactie
$filename
$filepath
'archive.zip'
$tmpfolder
Doen allemaal ongeveer hetzelfde wat het sowieso allemaal vreselijk verwarrend maakt.

Vooral dit:
readfile($filepath.$filename);
unlink($tmpfolder.'/archive.zip');
Terwijl het daar over precies hetzelfde pad+bestand gaat?

Je kunt de PHP los van het formulier/AJAX testen. Doe dit dan ook. Zorg dat dat werkt, en ga dan pas via AJAX testen.

Je zegt "readfile() werkt niet". Wat gebeurt er, en hoe wijkt dit af van het verwachte resultaat?

Enne, wellicht wil je $checkboxfiles onderwerpen aan een controle aan de hand van een whitelist, anders is het misschien mogelijk om arbitraire (en gevoelige) bestanden te downloaden zoals configuratiebestanden en dergelijke...
Ik heb het zonder ajax getest en dan werkt de readfile() wel! Maar met een ajax call niet. En na wat googlen begrijp ik nu dat dat komt omdat ajax de response in textvorm retourneert. Das het hekele punt.
@Thomas: maar blijkbaar wist jij dat ook niet anders had je me dat direct kunnen zeggen dat dat the main issue was
Heb je al gekeken in je browser naar de inhoud van je AJAX-request?
Problemen oplossen is dingen uitsluiten zodat je snel in kunt zoomen op het daadwerkelijke probleem(gebied). Als ik een vraagstuk voorgeschoteld krijg van de vorm stap A -> ... -> stap Z en iemand zegt "Ik voer X in in stap A en uit Z rolt niet het gewenste resultaat" dan zal ik altijd voorstellen om dit eens stap voor stap te doorlopen, ik ga echt niet door heel het vraagstuk heenspitten want vaak is dit lang niet de hele puzzel.

Los daarvan, uiteindelijk is het mijn doel om het probleemoplossend vermogen van de vragensteller te vergroten, en niet om enkel ad hoc antwoorden te geven op ad hoc vragen.

@Adoptive: over dat voorbeeld, hoe resulteert het echo'en van een pad+bestandsnaam in een downloadprompt? :/
EDIT: oh, window.location = response; lol, weet niet of ik dat zo zou programmeren.
Je moet dit ook niet via AJAX doen, maar gewoon een window.open() (waarbij je dus geen POST kunt doen, maar via de GET moet werken). Door de Content-Disposition: attachment header zal de browser snappen dat ie hiervoor geen nieuwe tab hoeft te openen (dat doet ie wel heel kort, maar die sluit ie meteen weer), maar een download dialoog aan moet bieden.
Op Mac wordt direct gedownload.
Op iPad komt onderaan het venster een mini dialoog om zip te downloaden en te openen in een app naar keuze.
Zou het niet logischer zijn dat je naar een download-actie wordt gestuurd via een script, in plaats van een rechtstreekse verwijzing naar een bestand (wat beschikbaar is in de publieke webdirectory)? Dan zou je een constructie als die van @Jack kunnen gebruiken.
Je kunt een (binair) bestand ook aan een ajax response meegeven. Maar dan moet je er wel tekst van maken. Zie base64_encode()

Ik gebruik dat om afgeschermde plaatjes op te halen.
Nu moet ik zeggen dat ik dat heb toegepast met plaatjes.

Voor pdf's verwijs ik door naar een nieuwe tab met een url, waarbij niet rechtstreeks de pdf wordt opgehaald, maar eerst PHP controleert of je bent ingelogd en dan wordt readfile() uitgevoerd.

Maar in principe is het mogelijk om de data met base64 over te sturen. En het is vast ook wel mogelijk om met javascript de output door te sturen. Maar ik had toen geen tijd om daar dieper in te duiken.

Reageren