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:
<a href="download.php?file=vw9586zw4m586vb.pdf">Kis Béla</a>
Szerver oldalon pedig:
<?php
function truncate_bytes($string, $len) {
  if (strlen($string) <= $len) {
    return $string;
  }
  if ((ord($string[$len]) < 0x80) || (ord($string[$len]) >= 0xC0)) {
    return substr($string, 0, $len);
  }
  while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0) {};
  return substr($string, 0, $len);
}

function mime_header_encode($string) {
  if (preg_match('/[^\x20-\x7E]/', $string)) {
    $chunk_size = 47; // floor((75 - strlen("=?UTF-8?B??=")) * 0.75);
    $len = strlen($string);
    $output = '';
    while ($len > 0) {
      $chunk = truncate_bytes($string, $chunk_size);
      $output .= ' =?UTF-8?B?'. base64_encode($chunk) ."?=\n";
      $c = strlen($chunk);
      $string = substr($string, $c);
      $len -= $c;
    }
    return trim($output);
  }
  return $string;
}
 
function serve_file($path, $filename, $mimetype = 'octet/stream') {
  $filesize = filesize($path);
  $headers = array(
    'Content-Description: File Transfer',
    'Content-Type: '. mime_header_encode($mimetype),
    'Content-Disposition: attachment; filename="'. mime_header_encode(basename($filename)) .'"',
    'Content-Transfer-Encoding: binary',
    'Content-Length: '. $filesize,
  );
  array_walk($headers, 'header');
  ob_clean();
  flush();
  readfile($path);
  exit();
}

$result = db_query('SELECT newname, origname, mimetype FROM files WHERE origname = "%s"', 
  $_GET['file']);
if ($file = db_fetch_array($result)) {
  serve_file($file['newname'], $file['origname'], $file['mimetype']);
}
else {
  header('HTTP/1.1 404 Not Found');
}

?>
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:

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
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.)