10 commenti apache, tutorial, php

Fornire agli utenti la possibilità di scaricare file attraverso il nostro sito web è un'operazione nel complesso semplice ma che richiede particolari accorgimenti.

 

Il modo più semplice per fare ciò prevede un normale tag <a> html con l'attributo href indicante il percorso al file.

<a href="file.zip" target="_blank">Scarica il file</a>

 

Questa tecnica è perfettamente funzionale per molte tipologie di file archivio: .zip, .tar, .gzip.

 

Al contrario, il comportamento predefinito dei browser per molte altre tipologie di file (ad esempio .pdf, .mp3, .doc) prevedono l'apertura di una nuova finestra.

Tale comportamento è possibile modificarlo inviando al browser gli opportuni headers così da far aprire la finestra del "Salva con nome" e consentire all'utente di salvarlo immediatamente sul proprio pc. In particolare l'headers in oggetto sarà:

Content-disposition: attachment;

 

Per inviare tale headers al browser possiamo impiegare due tecniche:

  1. la prima farà ricorso ad un file .htaccess;
  2. con la seconda, invece, il download del file e l'invio degli headers avverrà in modo indiretto tramite uno script php.

 

Forzare il download tramite .htaccess

In questo caso è utile collocare i file per il downaload in una cartella dedicata e al suo internoandremo a creare un file .htaccess con le seguenti istruzioni:

<FilesMatch "\.(?i:doc|xls|pdf|mp3|txt)">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

 

Così come impostato gli headers verranno modificati per i file con estensione doc, xls, pdf, mp3 e txt (ovviamente potete modificarlo a vostro piacimento eliminando i presenti o inserendone di nuovi).

A questo punto il semplice link come quello precedentemente descirtto (il tag <a>) ad uno di essi farà aprire la finestra del download secondo le specifiche dei vari browser.

 

Impostare gli header per il download con Php

Con la seconda tecnica il download del file avverrà attraverso un file php che farà da "filtro".

Ecco di seguito un codice di esempio di un file che chiameremo, ad esempio download.php:

<?php  
/*  
impostiamo la cartella in cui sono presenti  
i file per il download  
*/  
$dir = "download/";  
  
/*  
riceviamo via GET il file da scaricare 
la funzione basename la applichiamo al fine di evitare che  
utenti maliziosi possano eseguire percorsi nell'URL 
 */  
$file = isset($_GET['file']) ? basename( (string) $_GET['file'] ) : '';  
  
$path = $dir . $file;  

/* eseguiamo alcuni controlli preventivi */  
if($file==''){
	exit('Nessun file indicato');
	}
else if(!is_file($path)){  
    exit('Il file non esiste');  
    }  
else if(!is_readable($path)){  
    exit('Il file non ha i permessi per essere scaricato');  
    }  
    
/* otteniamo alcune info sul file */  
$info = pathinfo( $path );  
$extension = $info['extension']; // estensione  
$size = filesize($path); // dimensione in byte  
$time_file = date( 'r', filemtime( $path ) ); // time ultima modifica  
 
/* inviamo gli opportuni headers */  
/* alcuni di questi sono degli hack (trucchi)  
per farlo funzionare correttamente anche su alcune versioni di IE*/  
header('Content-Type: application/octet-stream');  
header('Content-Disposition: attachment; filename="'. basename($path) .'"');   
header('Content-Transfer-Encoding: binary');  
header('Content-Length: ' . $size);  
header('Last-Modified: ' . $time_file);  
header('Expires: 0');  
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');  
header('Pragma: public');  
    
/* eliminiamo eventuale output inviato */  
ob_clean();  
flush();  
  
/* leggiamo il file inviamo l'output */  
@readfile($path) or die('SERVER ERROR!');  
exit;  
?> 

 

A questo punto per consentire il download del file "document.pdf" faremo un link al file download.php indereno nella quesry string la variabile get "file", ovvero:

<a href="download.php?file=document.pdf" target="_blank">SCARICA IL FILE</a>

 

La classe ForceDownload

Essendo questa un operazione che integro spesso nei miei siti ho creato la classe ForceDownload la quale segue il medesimo approccio ma con la comodità di snellire tutta la procedura.

Ecco di seguito il link per il download della classe.

DOWNLOAD​​

Il suo utilizzo è molto semplice. Il file download.php sarà molto più sinteticamente il seguente:

<?php
require_once('ForceDownload.class.php');
$dir = "download/";  
$file = isset($_GET['file']) ?  $_GET['file']  : ''; 
$download = New ForceDownload($dir, $file);
$download->download() or die ($download->get_error());

 

Come in precedenza basterà un link al file downalod con indicazione nella query string nella variabile get "file" del nome del file.

 

Conclusioni

Le due tecniche sono descritte come alternative ma alle volte l'una è da preferire all'altra. Personalmente preferisco adottare quella con php dato.

 

Se hai avuto problemi nell'implementare tale funzionalità lasciami pure un commento. Se invece ti sono stato di aiuto condividi questo articolo sui social e iscriviti alla mia fan page così da essere aggiornato sui prossimi articoli.

Olimpio Romanella

Sono un appassionato di Web Developing con un particolare debole per php. Mi dedico principalmente dello sviluppo back-end ed in particolare programmazione lato server con php, sviluppo di database relazionali MySql e progettazione di CMS di piccole e medie dimensioni.

Mi avvalgo del framework javascript Jquery, utilizzando molti dei suoi plugin e nei dei miei progetti utilizzo spesso il framework MVC Codeigniter.

10 Commenti presenti

avatar Claudio

Claudio

20 May 2014 ore 17:29

Ciao Olimpio,
sto provando e riprovando lo script per il download di file, ma viene sempre visualizzata la finestra di dialogo.

Ho eseguito l'esempio che ho scaricato dal tuo sito, ma mi chiede sempre se voglio aprirlo oppure salvarlo.
Io vorrei che il download dei file contenuti all'interno della cartella venisse eseguito senza l'apertura della finestra di salvataggio.

avatar Olimpio Romanella

Olimpio Romanella

20 May 2014 ore 16:13

@Claudio: Provare per credere!

avatar Claudio

Claudio

20 May 2014 ore 09:16

avatar Ricky

Ricky

18 September 2013 ore 19:30

Grazie, dopo tante ore mi hai risolto un problema non da poco

avatar angelo

angelo

05 August 2013 ore 19:21

avatar angelo

angelo

05 August 2013 ore 19:04

avatar oly1982

oly1982

12 April 2013 ore 21:23

avatar riccardo

riccardo

12 April 2013 ore 12:45

avatar oly1982

oly1982

28 January 2012 ore 19:43

avatar Domenico

Domenico

28 January 2012 ore 18:58