PHP Force Download - univerzální stažení souboru pomocí header - icons.cz

PHP Force Download - univerzální stažení souboru pomocí header

Zřejmě každý začínající PHP vývojář se jednou setká s problémem jak vytvořit možnost stažení souboru aniž by uživatel měl možnost vidět přesnou adresu odkud soubor stahuje. Toto a spoustu dalších výhod nabízí jednoduchá funkce, kterou naleznete v článku.

Zdrojový kód funkce force download

<?php
function force_download ($data, $name, $mimetype='', $filesize=false) {
    // File size not set?
    if ($filesize == false OR !is_numeric($filesize)) {
        $filesize = strlen($data);
    }

    // Mimetype not set?
    if (empty($mimetype)) {
        $mimetype = 'application/octet-stream';
    }

    // Ujistíme se, že v souboru nejsou data navíc
    ob_clean_all();

    // Odeslání hlavičky
    header("Pragma: public"); // požadováno
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false); // požadováno u některých prohlížečů
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: " . $mimetype);
    header("Content-Length: " . $filesize);
    header("Content-Disposition: attachment; filename="" . $name . "";" );

    // Finální odeslání souboru
    echo $data;
    die();
}

function ob_clean_all () {
    $ob_active = ob_get_length () !== false;
    while($ob_active) {
        ob_end_clean();
        $ob_active = ob_get_length () !== false;
    }

    return true;
}
?>

Použití

Pro ty z vás co nejste zvyklí na použití vlastních definovaných funkcí, napíšu jednoduchý návod jak na to.

  1. Výše uvedený zdrojový kód si vložte do nějakého php souboru. Třeba download.php
  2. Tímto jste si nadefinovali funkci force_download(); kterou si následně zavoláme.
  3. force_download($data, $name, $mimetype);
  • $data – obsah souboru, který si načtete třeba pomocí funkce fread
  • $name – název souboru, který uživatel stáhne. Nesouvisí s názvem souboru uloženého na serveru
  • $mimetype – o jaký typ souboru se jedná.

Mimetypes a jejich koncovky

'hqx'   =>      'application/mac-binhex40',
'cpt'   =>      'application/mac-compactpro',
'csv'   =>      array('text/x-comma-separated-values', 'application/vnd.ms-excel'),
'bin'   =>      'application/macbinary',
'dms'   =>      'application/octet-stream',
'lha'   =>      'application/octet-stream',
'lzh'   =>      'application/octet-stream',
'exe'   =>      'application/octet-stream',
'class' =>      'application/octet-stream',
'psd'   =>      'application/x-photoshop',
'so'    =>      'application/octet-stream',
'sea'   =>      'application/octet-stream',
'dll'   =>      'application/octet-stream',
'oda'   =>      'application/oda',
'pdf'   =>      array('application/pdf', 'application/x-download'),
'ai'    =>      'application/postscript',
'eps'   =>      'application/postscript',
'ps'    =>      'application/postscript',
'smi'   =>      'application/smil',
'smil'  =>      'application/smil',
'mif'   =>      'application/vnd.mif',
'xls'   =>      array('application/excel', 'application/vnd.ms-excel'),
'ppt'   =>      'application/powerpoint',
'wbxml' =>      'application/wbxml',
'wmlc'  =>      'application/wmlc',
'dcr'   =>      'application/x-director',
'dir'   =>      'application/x-director',
'dxr'   =>      'application/x-director',
'dvi'   =>      'application/x-dvi',
'gtar'  =>      'application/x-gtar',
'gz'    =>      'application/x-gzip',
'php'   =>      'application/x-httpd-php',
'php4'  =>      'application/x-httpd-php',
'php3'  =>      'application/x-httpd-php',
'phtml' =>      'application/x-httpd-php',
'phps'  =>      'application/x-httpd-php-source',
'js'    =>      'application/x-javascript',
'swf'   =>      'application/x-shockwave-flash',
'sit'   =>      'application/x-stuffit',
'tar'   =>      'application/x-tar',
'tgz'   =>      'application/x-tar',
'xhtml' =>      'application/xhtml+xml',
'xht'   =>      'application/xhtml+xml',
'zip'   =>      array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
'mid'   =>      'audio/midi',
'midi'  =>      'audio/midi',
'mpga'  =>      'audio/mpeg',
'mp2'   =>      'audio/mpeg',
'mp3'   =>      'audio/mpeg',
'aif'   =>      'audio/x-aiff',
'aiff'  =>      'audio/x-aiff',
'aifc'  =>      'audio/x-aiff',
'ram'   =>      'audio/x-pn-realaudio',
'rm'    =>      'audio/x-pn-realaudio',
'rpm'   =>      'audio/x-pn-realaudio-plugin',
'ra'    =>      'audio/x-realaudio',
'rv'    =>      'video/vnd.rn-realvideo',
'wav'   =>      'audio/x-wav',
'bmp'   =>      'image/bmp',
'gif'   =>      'image/gif',
'jpeg'  =>      array('image/jpeg', 'image/pjpeg'),
'jpg'   =>      array('image/jpeg', 'image/pjpeg'),
'jpe'   =>      array('image/jpeg', 'image/pjpeg'),
'png'   =>      array('image/png',  'image/x-png'),
'tiff'  =>      'image/tiff',
'tif'   =>      'image/tiff',
'css'   =>      'text/css',
'html'  =>      'text/html',
'htm'   =>      'text/html',
'shtml' =>      'text/html',
'txt'   =>      'text/plain',
'text'  =>      'text/plain',
'log'   =>      array('text/plain', 'text/x-log'),
'rtx'   =>      'text/richtext',
'rtf'   =>      'text/rtf',
'xml'   =>      'text/xml',
'xsl'   =>      'text/xml',
'mpeg'  =>      'video/mpeg',
'mpg'   =>      'video/mpeg',
'mpe'   =>      'video/mpeg',
'qt'    =>      'video/quicktime',
'mov'   =>      'video/quicktime',
'avi'   =>      'video/x-msvideo',
'movie' =>      'video/x-sgi-movie',
'doc'   =>      'application/msword',
'word'  =>      array('application/msword', 'application/octet-stream'),
'xl'    =>      'application/excel',
'eml'   =>      'message/rfc822'

Proč řešit download právě touto cestou?

Uvedu jednoduchý příklad. Máte webový projekt, kde nabízíte soubory komisním prodejem. Uživatel si zaplatí za jeden soubor a vy mu poskytnete url na které si může požadovaný soubor stáhnout. Tato url může vypadat následovně:

  • http://stranka.cz/cesta/k/ulozenemu/souboru.zip

Prostý uživatel si soubor stáhne a je spokojen. Ovšem zaběhlejšímu uživatelovi už ale může dojit, že v tom samém adresáři budou zřejmě uložené i ostatní soubory a začne tipovat názvy ostatních. A profík už si jednoduše zjistí podle čeho je konkrétní název odvozen a už stahuje celkem na jisto. Samozřejmě lze název zakódovat do md5 atd., ale to už mi nepřijde jako zrovna „elegantní“ řešení.

  • http://stranka.cz/download.php?soubor={id_souboru}

Tímto způsobem nedáte uživateli žádnou možnost aby zjistil odkud soubor pochází. A pokud jste ještě více paranoidní, tak můžete místo id použít třeba již výše zmíněný zakódovaný string. Toto řešení mi přijde nejlepší jak z bezpečnostního hlediska, tak i z hlediska usnadnění práce a to se přece taky počítá ne? :)

hibi, 03:50, 29.3.2008, Internet


Komentáře k textu

frant
16:27, 10.6.2008

http://stranka.cz/download.php?sou­bor={id_souboru}

uziv pak netypuje nazvy souboru, ale id.

Je treba dodat, ze se pak musi kontrolovat, zda ma uziv k tomuto id pravo (muze ho stahovat)

hibi
16:56, 10.6.2008

Je to pojaté univerzálně a tímto stylem lze opravdu ochranu před nevyžádaným stážením ošetřit mnoha způsoby. Jedním z nich je třeba ten co zmiňujete…

ii
15:22, 2.4.2010
8-O
skr
18:41, 29.4.2011

header(„Content-Type: " . $mimetype); header(“Content-Length: " . $filesize); header(„Content-Disposition: attachment; filename="" . $name . "";“ );

opravit

Jonatan
16:08, 16.12.2017

Diky za clanek ;)

Jaký je Váš názor?


Kliknutím vložíš: Vlož smajla :-) Vlož smajla :-( Vlož smajla ;-) Vlož smajla :-D Vlož smajla 8-O Vlož smajla 8-) Vlož smajla :-? Vlož smajla :-x Vlož smajla :-P Vlož smajla :-|

Tagy a štítky

php stahnout soubor header application/octet-stream application/force stažení php souboru octet stream php force download octet-stream stažení souboru php download souboru php stazeni souboru header mime type: application/octet-stream php download souboru php odeslání souboru pdf stažení souboru přes header


TOPlist