Tiedostolataus

eis 28.04.06 23:13

Skripti, joka mahdollistaa tiedostojen latailujen vähän hankalammissakin ympäristöissä. Lisätty, kun kyselty eri paikoissa.

 Tekstiversio  Arvo: 5 (11 ääntä)  Äänestä: +  -
<?php

// useampikin henkilö on tätä ollut vääntämässä, joten ei ehkä kannattane
// niitä copyright-juttuja pistää.. käytä miten haluat.

  $fileDir = "/polku/lataus/hakemistoon"; // Määritellään polku, ei kauttaviivaa loppuun
  $fileName = "tiedosto.zip"; // Tiedostonimi, voidaan noutaa dynaamisesti myös esim. SQL-kyselyllä


  $fileString=$fileDir.'/'.$fileName; // Polun ja tiedostonimen yhdistelmä
  // Muunnetaan tiedostonimet IE:lle kelvollisiksi
  if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")){
    $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
  }  // Varmistetaan tiedoston olemassaolo ennen headerien lähettämistä
  if (!$fdl=@fopen($fileString,'r')){
    die ("Virhe: tiedostoa ei ole.");
  } else {
    header("Cache-Control: "); // Jätetään tyhjäksi IE-ongelmien välttämiseksi
    header("Pragma: "); // Jätetään tyhjäksi IE-ongelmien välttämiseksi
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"".$fileName."\"");
    header("Content-Length:".(string)(filesize($fileString)));
    sleep(1); // ilman tätä jotkut >32kt tiedostot aiheuttavat ongelmia
    // vaihtoehtoinen fpassthru ja readfile-funkkareille, käyttää vähemmän muistia:
    while(!feof($fdl)) {
      $buffer = fread($fdl, 4096);
      print $buffer;
    }
    fclose($fdl);
     // tähän kohtaan voi laittaa vaikka SQL-kyselyn päivittämään latauskertojen laskuria niin halutessaan
  }

 ?>

editoitu: 08:39 29.4.06
ajv 08:33 29.4.06 
No ensimmäinen kommenti mikä tulee mieleen on se, että kun tää kummiskin "copy-pastetaan ämbeenettiin" ja jos tuo tuo ladattavan tiedoston nimi tulee osoiteriviltä ($_GET['filename']), niin kannataisi tarkistaa, että se ei sisällä esim "../index.php". Ei nyt tohon sitä tartte laittaa, mutta tiedoksi käyttäjille kuitenkin.
eis 01:08 30.4.06 
Jooh. $_GET:stä sitä tuskin kannattaa edes ottaa jos sen voi välttää, mut mikäli tiedostoja on paljon niin sitten se taitaa siihen mennä. Tässä tapauksessa kannattanee käyttää basename-funkkaria sen varmistamiseen, että parametrina tosiaan tulee vain tiedostonnimi eikä polkua.
editoitu: 11:53 3.5.06
Ztane 11:52 3.5.06 
hmm, millä perusteella tuo 4096 readi käyttää vähemmän muistia ko fpassthru?

Ja minkä takia tämä koodi löytyy http://fi2.php.net/fpassthru ?
Jokikotka 12:35 3.5.06 
fpassthru taitaapi lukea koko tiedoston muistiin ennenkuin se tulostaa sen, sen takia toi looppi on parempi. =)
Ztane 11:11 5.5.06 
"taitaapi"?
editoitu: 21:10 7.5.06
eis 20:33 7.5.06 
Ztane kirjoitti:
hmm, millä perusteella tuo 4096 readi käyttää vähemmän muistia ko fpassthru?

Koska fpassthru lukee koko tiedoston kerralla muistiin.

Ja minkä takia tämä koodi löytyy http://fi2.php.net/fpassthru ?

Ei löydy ihan tuollaisenaan, mutta juu, kommenteista vähän soveltamalla toi on tosiaan tehty. Lisätty lähinnä siksi että foorumeilla tuota toistuvasti on kyselty eikä tuota ihan tuollaisena missään ollut (http://mureakuha.com/keskustelut/2?12076, http://mureakuha.com/keskustelut/2?9844, http://mureakuha.com/keskustelut/2?10082 jne).
Ztane 07:40 17.5.06 
Hahhah, nyt luin nuo kommentit tuosta fpassthrusta. PHP todellakin on siis paska. Esmes linuxissa sendfile syscall olis ehdoton vaihtoehto moiseen.