ugrás a tartalomhoz

Ékezetes fájlnévre mutató linkek

barii · 2010. Szep. 20. (H), 11.28
Sziasztok!

Van az oldalon egy fájlfeltöltés, ahol fel lehet tölteni fájlokat, ékezetteleníteni nem kéne, namost én pont úgy kezelem, mintha ékezet nélkül lenne, és működik. Simán megnyotja a .../files/egy ékezetes fájl.txt fájlt.
Szól ez ellen valami érv? hogy miért ne használjam?

Illetve ha azt mondjátok, hogy szól, akkor hogy kéne? Ami elsőre eszembe jut, hogy pl van a fent írt fájl, akkor apache mod_rewrite-al átirányitani mondjuk fajl.php?f=123, és van egy adatbázis bejegyzés, ahol 123 | .../files/egy ékezetes fájl.txt, viszont akkor hogy kéne kinézzen a fajl.php?

köszi
 
1

Szól

janoszen · 2010. Szep. 20. (H), 11.41
Több érv is szól ellene. Egyrészt ha ne adj' Isten egyszer költöznöd kell egy olyan szerverre, aminek más a default karakterkódolása és nem vagy nagyon észnél, akkor szomorú leszel. Másrészt ugye ülhetsz olyan gép előtt, amin nincs ékezet.

Ami a megoldást illeti, úgy kéne csinálni, hogy amikor feltöltődik a fájl, adsz neki valami kellően random nevet és a nevét eltárolod az adatbázisban. Ezt aztán teljes nyugalommal odaadhatod a böngészőnek. A PHP-s mókát én nem csinálnám, mert elesel az oprendszer sendfile és cache támogatásától, ergó fölöslegesen eszi a CPU-t a kiszolgálás.
2

Egy kicsit ezt kifejtenéd

csaba86 · 2010. Szep. 20. (H), 16.47
Egy kicsit ezt kifejtenéd bővebben? Olvastam mit írtál és felkeltette az érdeklődésem! :)

Konkrétan ez érdekelne, hogy mit értesz ez alatt.
"elesel az oprendszer sendfile és cache támogatásától"

Semmi kód nem kell, csak egy picit bővebb fejtágítás, a többinek majd utánanézek! Köszi!
3

Sendfile

janoszen · 2010. Szep. 20. (H), 17.18
A sendfile a Linux operációs rendszer egy zseniális találmánya. Ha a szerver (Apache, LigHTTPd, stb) úgy érzi, hogy egy fájlt csak bele kell küldeni egy socketbe, akkor élhet a sendfile() kernel hívással. Ezzel azt éri el, hogy a kernel olvassa föl a fájlt a diskről és küldi bele a socketbe. Ez azért gyorsabb, mert a user space programoknak bizonyos műveletek elvégzéséhez a kerneltől kell segítséget kérni, ami idő.

Az oprendszer file cache részben használható lesz számodra, ha PHP-ból szolgálsz ki, hiszen a fájl felolvasásakor bekerül a memóriába, de ha a fájllal bármiféle transzformációt is végzel, akkor már ez is részben bukta.
7

Köszönöm!

csaba86 · 2010. Szep. 27. (H), 21.30
Szóval magyarán ne pl /letolt.php?file=ezkell.jpg hanem simán /ezkell.jpg

Utóbbi meg automatikusan "sendfile"-os lesz akkor?
8

Így van

janoszen · 2010. Szep. 28. (K), 07.45
Így van, a szerver ugyanis statikus fájlt szolgál ki.
4

szia, köszönöm a választ a

barii · 2010. Szep. 22. (Sze), 10.08
szia, köszönöm a választ
a lényeg az, hogy amikor az user letölti a fájlt, akkor az eredeti, ékezetes, szóközös fájlt töltse le.
ezt találtam:
http://www.zubrag.com/scripts/download.php
szóval pl lehetne igy csinálni: (?)
<a href=".../download.php?f=random_fajlnev.zip&fc=ékezetes fájlnév">link</a>
de ilyenkor hogy is kéne? fc=ékezetes fájlnév nyilván kodolva kell legyen a linkben. Akkor ebbe a kodba bele kéne irni, hogy a $_GET['fc']-t kodoljam vissza, vagy az automatikus?
de a lényeg, hogy ez a kód kb. jó lesz nekem, igaz?
5

Mint írtam

janoszen · 2010. Szep. 22. (Sze), 10.58
Mint fentebb írtam, nagyon komoly problémákba fogsz ütközni, ha bármilyen szinten foglalkozol ékezetes fájlnevekkel a fájlrendszerben, a PHP fájlkiszolgálás meg CPU-t zabál tök fölöslegesen.
6

akkor tudnál valami linket

barii · 2010. Szep. 27. (H), 19.59
akkor tudnál valami linket adni a jó megoldásra?
9

Nem

janoszen · 2010. Szep. 28. (K), 07.51
Nem nagyon, mert erre nincs dobozos megoldás. Viszont elmondom, mit kell tenned:

Ha a uses az admin felületen feltölt egy fájlt, generálsz egy véletlenszerű md5 hasht és ezen a néven mented el a fájlt. Az adatbázisodba beírod a hasht és az általa adott nevet is, majd amikor listázni kell, nem mappát olvasol, hanem adatbázist.
10

Ha csak egy md5 hasht

_subi_ · 2010. Szep. 28. (K), 17.51
Ha csak egy md5 hasht generál, van elméleti esélye az ütközésnek. Akkor, ahogy mondanád, szomorú lenne. :) Én még hozzácsapnám pl. az id-t.
11

Elmélet

janoszen · 2010. Szep. 28. (K), 20.39
Ha elég jó az entrópia forrás, gyakorlatilag kizárt. De elvben persze igazad van.
12

nem az a baj, hogy hogy

barii · 2010. Szep. 29. (Sze), 13.30
nem az a baj, hogy hogy mentem ki, hanem hogy hogy adom vissza.
vagy egy "Kis Béla.pdf"-em, addig világos, hogy elmentem adatbázisba, hogy
vw9586zw4m586vb.pdf | Kis Béla.pdf
vagy lehet ez akár
kis_bela.pdf | Kis Béla.pdf is
csak milyen linket teszek ki utána?
mert nyilván <a href="kis_bela.pdf">Kis Béla</a> működik, csak akkor az ékezet nélküli fájlt fogja letölteni
azt hogy teszem ki neki, hogy ékezetesen tudja letölteni a fájlt?
13

Kiszolgálás

Poetro · 2010. Szep. 29. (Sze), 13.55
Azt hogy ezt hogyan szolgálod ki, az a lényeges. Teheted mondjuk azt, hogy:
  1. <a href="download.php?file=vw9586zw4m586vb.pdf">Kis Béla</a>  
Szerver oldalon pedig:
  1. <?php  
  2. function truncate_bytes($string$len) {  
  3.   if (strlen($string) <= $len) {  
  4.     return $string;  
  5.   }  
  6.   if ((ord($string[$len]) < 0x80) || (ord($string[$len]) >= 0xC0)) {  
  7.     return substr($string, 0, $len);  
  8.   }  
  9.   while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0) {};  
  10.   return substr($string, 0, $len);  
  11. }  
  12.   
  13. function mime_header_encode($string) {  
  14.   if (preg_match('/[^\x20-\x7E]/'$string)) {  
  15.     $chunk_size = 47; // floor((75 - strlen("=?UTF-8?B??=")) * 0.75);  
  16.     $len = strlen($string);  
  17.     $output = '';  
  18.     while ($len > 0) {  
  19.       $chunk = truncate_bytes($string$chunk_size);  
  20.       $output .= ' =?UTF-8?B?'base64_encode($chunk) ."?=\n";  
  21.       $c = strlen($chunk);  
  22.       $string = substr($string$c);  
  23.       $len -= $c;  
  24.     }  
  25.     return trim($output);  
  26.   }  
  27.   return $string;  
  28. }  
  29.    
  30. function serve_file($path$filename$mimetype = 'octet/stream') {  
  31.   $filesize = filesize($path);  
  32.   $headers = array(  
  33.     'Content-Description: File Transfer',  
  34.     'Content-Type: '. mime_header_encode($mimetype),  
  35.     'Content-Disposition: attachment; filename="'. mime_header_encode(basename($filename)) .'"',  
  36.     'Content-Transfer-Encoding: binary',  
  37.     'Content-Length: '$filesize,  
  38.   );  
  39.   array_walk($headers'header');  
  40.   ob_clean();  
  41.   flush();  
  42.   readfile($path);  
  43.   exit();  
  44. }  
  45.   
  46. $result = db_query('SELECT newname, origname, mimetype FROM files WHERE origname = "%s"',   
  47.   $_GET['file']);  
  48. if ($file = db_fetch_array($result)) {  
  49.   serve_file($file['newname'], $file['origname'], $file['mimetype']);  
  50. }  
  51. else {  
  52.   header('HTTP/1.1 404 Not Found');  
  53. }  
  54.   
  55. ?>  
14

Sendfile-al így? :)

csaba86 · 2010. Szep. 29. (Sze), 16.02
Kicsit utánanéztem a sendfile php-vel való együttműködésének és ezt találtam. Ha ezen az elvan kikeresi az adatbázisból, hogy mely file-ra gondolt akkor ez működne? Kipróbálni még nem tudtam.

senfile

Utólag jobban átgondoltam, lehet mégse teljesen jót találtam, de ha nem is jó teljesen a kód, akkor csak nézzük ezt:
  1. header('Content-Description: File Transfer');  
  2. header('Content-Type: application/octet-stream');  
  3. header('Content-Disposition: attachment; filename='.basename($file));  
  4. header('Content-Transfer-Encoding: binary');  
  5. header('Expires: 0');  
  6. header('Cache-Control: must-revalidate, post-check=0, pre-check=0');  
  7. header('Pragma: public');  
  8. header('Content-Length: ' . filesize($file));  
(bocsi, hogy próbálok okoskodni)
15

Nem!

janoszen · 2010. Szep. 29. (Sze), 18.39
Ez megint a PHP-vel való fájlkiszolgálás esete. A jó megoldás, hogy eleve a link címét nyered ki. Ha minden áron azt akarod, hogy az eredeti fájlnév látsszon a letöltés után, nézd meg a webszervered doksiját. Ha jól emlékezem, van a LigHTTPd-ben olyan funkció, hogy egy HTTP fejléccel tudod arra utasítani, hogy szolgáljon ki egy fájlt.
17

Gyerekes dolog az offolás és

csaba86 · 2010. Szep. 29. (Sze), 20.10
Gyerekes dolog az offolás és szerintem ez már az a kategória, de azt hiszem megtaláltam amit mondtál. A neve Xsendfile, egy modul LigHTTPd-hez és Apache-hoz.

Köszi a segítséget, de tényleg, ha pedig mégse ez, ígérem nem kommentelek megint! :)
16

Nem!

janoszen · 2010. Szep. 29. (Sze), 18.42
Ez megint a PHP-vel való fájlkiszolgálás esete. A jó megoldás, hogy eleve a link címét nyered ki. Ha minden áron azt akarod, hogy az eredeti fájlnév látsszon a letöltés után, nézd meg a webszervered doksiját. Ha jól emlékezem, van a LigHTTPd-ben olyan funkció, hogy egy HTTP fejléccel tudod arra utasítani, hogy szolgáljon ki egy fájlt.
22

mod_xsendfile

gabesz666 · 2013. Feb. 11. (H), 15.51
Ha apache-od van és te üzemelteted a rendszert (vagy telepítve van a modul), akkor a mod_xsendfile lehet a barátod. Ékezetes fájlnév (vagy ha például van a fájlnévben ".valamikiterjesztés" substring) esetén csinálhatsz egy url rewrite-ot, ami meghív egy php-t, ami lekéri adatbázisból a fájlnévhez tartozó valós (ékezetmentes) fájlnevet. Ezt a fájlt pedig csak szimplán kiküldöd az X-Sendfile headerrel. Ezzel a módszerrel nem kell php-vel beolvasni a fájlt, az oldaladon is megmarad az ékezetes fájlnév a linkekben, viszont a szerveren tudod tárolni tetszőleges névvel a fájlt.
18

továbbra is köszönöm a

barii · 2010. Okt. 3. (V), 15.58
továbbra is köszönöm a segítséget, a kóddal kapcsolatban egy kérdés:
1. <a href="download.php?file=vw9586zw4m586vb.pdf">Kis Béla</a>
ez itt az ékezet/szóköz nélküli hash, ez világos
# $result = db_query('SELECT newname, origname, mimetype FROM files WHERE origname = "%s"',
# $_GET['file']);

tehát itt a $_GET['file'] is az
de a query-ban origname van, akkor ez elírás, és a where-ben newname kéne legyen?
19

bit.ly megoldás

lebowski71 · 2013. Feb. 11. (H), 13.05
Én ezt úgy oldottam meg, hogy regisztráltam a bit.ly nevű url shortoló szolgáltatáshoz.
Az ékezetes fájlneveket is gyönyörűen kezeli.
Tehát feltöltöm az ékezetes fájlt, ott php-val generálok neki egy bit.ly url-t, és azzal már azt csinálsz amit akarsz, pl eltárolhatod mysql táblába.
így kell gondozni: http://davidwalsh.name/bitly-php
20

Kérdések

Hidvégi Gábor · 2013. Feb. 11. (H), 13.24
Az általad vázolt megoldás kétségkívül kényelmes. A következők a kérdéseim:
  • mi van akkor, ha a bit.ly nem működik?
  • mi van akkor, ha a felhasználónál tiltva van a bit.ly?
  • honnan tudja a felhasználó, hogy mit tölt le? (a kódolt fájlnév mögött bármi lehet)
21

Re: Kérdések

lebowski71 · 2013. Feb. 11. (H), 14.56
Jogos kérdések. :)
Ez a saját megoldásom, nekem ez egyszerű volt, és még eddig bevált. Mivel nálunk a hozzáféréseket is én menedzselem, így nem volt kérdés, hogy hozzáférnek-e.
Mellesleg ha a twitternek ez az url kezelés megfelel akkor nekem is.
(Még annyit, hogy a tinyurl nekem nem kezelte az ékezetes fájlneveket.)