Posílání souborů pod správným názvem
Pokud chceme některé soubory ke stažení zpřístupnit jen vybraným uživatelům, je vhodné je učinit přímo přes web nepřístupné (v Apache např. umístěním mimo DocumentRoot nebo do adresáře s omezeným přístupem). Pokud to neuděláme, vystavujeme se riziku, že cestu k souboru uživatel uhodne nebo jinak zjistí a stáhne si soubor bez ověření. Po ověření práv je tedy nejlepší soubor uživateli poslat přímo PHP skriptem. Tomu se nevyhneme ani v případě, kdy je soubor uložen v databázi a přímá cesta k němu neexistuje.
Aby prohlížeč věděl, co si se souborem má počít, musíme ho samozřejmě poslat se správným Content-Type. Pokud soubor chceme navíc poslat pod správným názvem, už to tak jednoduché bohužel není. Hlavička Content-Disposition, pomocí které se název souboru dá předat, je sice široce implementovaná, v HTTP ale přímo není a některé proxy ji opravdu ignorují. Pokud tedy nechceme uživateli např. spustitelný soubor posílat pod názvem stahnout.php
, nelze se na tuto hlavičku spolehnout.
<?php // zde ověřit, jestli má uživatel k souboru $_GET["filename"] právo header("Content-Type: application/octet-stream"); // při stažení přes některé proxy servery se název souboru nepředá header("Content-Disposition: attachment; filename=\"$_GET[filename]\""); readfile("data/$_GET[filename]"); ?>
Řešit se to dá tak, že název souboru uvedeme jako poslední část URL. V Apache je možné zapnout direktivu AcceptPathInfo a použít cestu stahnout.php/aplikace.exe
.
<?php $filename = substr($_SERVER["PHP_SELF"], strlen($_SERVER["SCRIPT_NAME"]) + 1); // zde ověřit, jestli má uživatel k souboru $filename právo header("Content-Type: application/octet-stream"); readfile("data/$filename"); ?>
Tento problém lze pochopitelně řešit i pomocí mod_rewrite například pravidlem RewriteRule ^/data/(.*) /stahnout.php?filename=$1
.
Diskuse
dgx:
To je vskutku fikané řešení :-)
Jen by mě zajímalo, jak časté jsou proxy, co Content-Disposition nepodporují. Jestli je to jedna z tisíce nebo třeba každá desátá.

Jakub Vrána
:
Poměr špatných bohužel neznám, každopádně jsem se s tím už setkal a musel jsem to řešit.


pck:
Dobry Den!V celom mojom portali pouzivam kodovanie UTF-8. Nazvy suborov mam ulozenu v databaze tiez kodovane s UTF-8. Pri stiahnuti suborov s hore spomenutou metodou dostanem necitatelne znaky v mene suborov. Vedeli by ste mi pomoct?
MiSHAK.wz.cz:
teoreticky pri zacatku spojeni nastavit kodovani komunikace na iso-8859-1 je to nejaka fce mysql staci pohledat

Mirek Renda:
Dobrý den,z aplikace posíláme obdobným způsobem PDF. Na majoritě počítačů to v pohodě přijde do prohlížeče, vyhodí systémový dialog otevřít/uložit atd.
Na pár počítačích to otevře prázdné okno IE, které zůstane viset (nejde zavřít, nutné shodit IE nebo restartovat).
Nedaří se mi příjít, kde je problém.
Matně si pamatuji, že jsme kdysi měli problém s pořadím jednotlivých hlaviček, ale už si nevybavím příčiny ani důsledky.
Neřešil jste to někdo? Dím moc. MR
Jakub Vrána
:
Podívejte se, jaké hlavičky vrací bezproblémové stažení souboru (bez PHP wrapperu) a pošlete ty stejné. Pokud navíc URL bude vypadat jako skutečný soubor se správnou koncovkou (zajistitelné např. pomocí mod_rewrite), tak to prostě musí fungovat.
Pokud se vám podaří dohledat příčinu chyby, tak ji sem prosím napište.


Diskuse je zrušena z důvodu spamu.

