Virtuální disk – souborová nástěnka v PHP

18. srpna 2002

Virtuální disk umožňuje ukládat soubory na webový server, kde si je návštěvníci stránek mohou stáhnout. Základní aplikace umožní komukoli soubory nahrávat, stahovat, ale i mazat. Díky využití databáze je možné si výpis souborů snadno setřídit podle názvů souborů, podle počtu stažení nebo podle data vložení.

Ke každému souboru je také připojen komentář. Aplikace se hodí pro intranet, pro použití v internetu by bylo vhodné oddělit část pro vkládání a mazání souborů od části, ve které je možné soubory stahovat. Přihlášení je potom možné vyřešit pomocí HTTP autentizace.

Pro lepší představu si můžete vyzkoušet ukázku, k dispozici je i zdrojový kód. V aplikaci jsou využity postupy, které již byly popsány zde na Intervalu, proto vynechávám detailní vysvětlování principu funkce.

Struktura tabulky databáze:

CREATE TABLE vdisk
(
filename varchar(50) NOT NULL default “,
comment text NOT NULL,
filesize int(20) NOT NULL default ‚0‘,
dloaded int(11) NOT NULL default ‚0‘,
filetime datetime NOT NULL default ‚0000-00-00 00:00:00‘,
PRIMARY KEY (filename),
UNIQUE KEY filename (filename)
)

Aplikace bude využívat hlavní skript index.php, a podpůrné skripty (ve složce handle). Potřebná nastavení includujeme souborem config.php:

<?php
$now = gmdate(‚D, d M Y H:i:s‘) . ‚ GMT‘;
header(‚Expires: 0‘); // rfc2616 – Section 14.21
header(‚Last-Modified: ‚.$now);
header(‚Cache-Control: no-store, no-cache, must-revalidate‘); // HTTP/1.1
header(‚Cache-Control: pre-check=0, post-check=0, max-age=0‘); // HTTP/1.1
header(‚Pragma: no-cache‘); // HTTP/1.0
set_time_limit(90);
set_magic_quotes_runtime(1);
$dbappname=“;
$store_files=‘./files/‘;
?>

Zde se nastaví odeslání hlaviček, které zamezí cachování dokumentu. Prodloužíme také maximální povolenou dobu běhu skriptu (v případě potřeby ji můžeme ještě zvýšit, více jak 200 bych asi nedával), nastavíme automatické vkládání zpětných lomítek před nebezpečné znaky, nastavíme proměnnou, která slouží jako předpona tabulky databáze (v ukázce je prázdná) a cestu ke složce, ve které budou ukládány soubory na serveru.

Hlavní index.php skript může vypadat podobně jako tento v naší ukázce – ten vkládá soubory předávané parametrem v URL:

<?php
require(‚handle/config.php‘);
require(‚handle/opendb.php‘);
if (empty($_GET[‚app‘]))
  $_GET[‚app‘]=’vdisk‘;
?><html>
<head>
<meta http-equiv=“Content-Type“ content=“text/html; charset=iso-8859-2″>
<title>Virtuální disk</title>
</head>
<body>
<?php include(‚handle/‘.$_GET[‚app‘].‘.php‘) ?>
<br /><br />
<a href=“index.php?app=vdisk&amp;sort=<?php echo $_GET[‚sort‘] ?>“>VDisk</a>
<a href=“index.php?app=vdisk_upload&amp;sort=<?php echo $_GET[‚sort‘] ?>“>Nový soubor</a>
</body>
</html>

Tento skript je jen ukázkou, ošetření parametru pro include je potřeba provést důkladněji. Povšimněte si odkazů, které jsou vypisovány na konci stránky. Předáváno je nejen jméno skriptu, ale také parametr sort, který bude popsán dále.

Formulář pro upload souboru vdisk_upload.php:

<?php
if (empty($_FILES[‚soubor‘][‚name‘]))
{
?>
<script language=“Javascript“ type=“text/javascript“>
function Control(theForm)
{
  for(var i=0; i<theForm.length; i++ )
  with(theForm.elements[i])
  {
    if( value.length==0)
   {
     alert(‚Zadejte potřebné údaje!‘);
     focus();
     return false;
    }
  }
  return true;
}
</script>
<fieldset>
<legend>Nahrát soubor <br /></legend>
<form id=“upload“ action=“index.php?app=vdisk_upload&amp;sort=<?php echo $_GET[‚sort‘] ?>“ method=“post“ enctype=“multipart/form-data“ onSubmit=“return Control(this)“>
Soubor:<br />
<input type=“file“ name=“soubor“ size=“32″ /><br />
Popis<br />
<textarea name=“comment“ rows=“5″ cols=“40″></textarea><br />
<input type=“Submit“ value=“Upload“ /><br />
</form>
</fieldset>
<?php
}
else
{
  $mess=’Soubor a informace o něm byly uloženy<br />‘;
  if (File_Exists ($store_files.$_FILES[‚soubor‘][‚name‘]))
    $mess=’Soubor ‚.$_FILES[‚soubor‘][‚name‘].‘ je již uložen na disku!<br />‘;
  else
  {
    if (@move_uploaded_file($_FILES[‚soubor‘][‚tmp_name‘], $store_files.$_FILES[‚soubor‘][‚name‘]))
    {
      if (!@mysql_query(„INSERT INTO „.$dbappname.“vdisk VALUES (‚“.$_FILES[‚soubor‘][‚name‘].“‚,'“.$_POST[‚comment‘].“‚,'“.$_FILES[‚soubor‘][‚size‘].“‚,0,NOW())“))
        $mess=’Soubor je uložen na disku, ale informace o něm se nezdařilo uložit!<br />‘;
    }
    else
      $mess=’Soubor se nezdařilo uložit na disk!<br />‘;
?>
Název: <?php echo $_FILES[‚soubor‘][‚name‘] ?><br />
Velikost: <?php echo ($_FILES[‚soubor‘][‚size‘]) ?>&nbsp;B<br />
Typ: <?php echo $_FILES[‚soubor‘][‚type‘] ?><br />
Popis: <?php echo $_POST[‚comment‘] ?><br />
<?php
  }
  echo $mess;
}
?>

Při zadávání údajů do formuláře je pomocí JavaScriptu kontrolováno vyplnění polí. Po úspěšném uploadu souboru z formuláře na server uložíme údaje do tabulky databáze. Ve skriptu jsou ošetřeny chyby, které mohou nastat – chyba při uploadu souboru, chyba při ukládání souboru do správné složky a chyba při zápisu do databáze. Naopak není kontrolován typ souboru a jeho velikost, je možné uložit libovolný typ souboru, teoreticky libovolně velký. Prakticky je velikost souboru omezena nastavením PHP (obvykle je povolená hodnota mezi 2 až 8 MB) a také tím, že upload velkého souboru trvá určitou dobu a protokol HTTP pro toto není vhodný, aplikace se tedy nehodí pro velké soubory. Vzhledem k zamýšlenému nasazení v intranetu a také pro zjednodušení zde není ošetřeno vkládání HTML kódu do komentáře souboru.

Seznam souborů zobrazuje hlavní skript vdisk.php:

<script language=“JavaScript“ type=“text/javascript“>
<!–
function EraseOK()
{
  delyes=confirm(‚Opravdu chcete soubor nenávratně odstranit?‘)
  if (delyes)
  {
    return true;
  }
  return false;
}
function DLoadInfo()
{
  alert(‚Pokud se soubor nezačne stahovat, zvolte pravým tlačítkem myši\n „Uložit cíl jako…“‚);
}
// –>
</script>
<table border=“0″ cellpadding=“4″ cellspacing=“0″>
<tr>
<th><a href=“index.php?app=vdisk&amp;sort=0″>soubor</a></th>
<th><a href=“index.php?app=vdisk&amp;sort=1″>stažen</a></th>
<th><a href=“index.php?app=vdisk&amp;sort=2″>velikost</a></th>
<th><a href=“index.php?app=vdisk&amp;sort=3″>vložen</a></th>
</tr>
<?php
switch ($_GET[‚sort‘])
{
  case 0:
  $order = ‚filename‘;
  break;
  case 1:
    $order = ‚dloaded DESC‘;
  break;
  case 2:
    $order = ‚filesize DESC‘;
  break;
  case 3:
    $order = ‚filetime DESC‘;
  break;
  default:
    $order = filename;
}
$soubory = @MySQL_Query(„SELECT filename, comment, dloaded, filesize, UNIX_TIMESTAMP(filetime) as time FROM „.$dbappname.“vdisk ORDER BY $order“);
while ($data=@MySQL_Fetch_Array($soubory))
{
?>
<tr>
<td valign=“top“><img src=“images/file.gif“ align=“left“ width=“27″ height=“32″ border=“0″ alt=““ />
[<a href=“index.php?app=vdisk_delete&amp;file=<?php echo StripSlashes($data[‚filename‘]) ?>“ title=“odstranit“ onClick=“return EraseOK()“>x</a>] [<a href=“vdownload.php?file=<?php echo StripSlashes($data[‚filename‘]) ?>“title=“stáhnout soubor“ onClick=“DLoadInfo()“><?php echo StripSlashes($data[‚filename‘]) ?></a>]<br />
<small><?php echo StripSlashes($data[comment]) ?></td>
<td valign=“top“><?php echo $data[dloaded] ?>x</td>
<td valign=“top“><?php echo round($data[filesize]/1024,2) ?> kB</td>
<td valign=“top“><?php echo date(‚d.m.Y h.i‘,$data[‚time‘]) ?></td>
</tr>
<tr><td colspan=“4″><hr></td></tr>
<?php
}
?>
</table>
<?php include(‚handle/vdisk_upload.php‘) ?>

Skript načte do pole obsah tabulky databáze se soubory a vypíše je do tabulky ve stránce. Nadpisy v záhlaví tabulky jsou zároveň odkazy, kterými je možné volit způsob setřídění seznamu souborů – podle předaného parametru sort se ve skriptu zvolí část SQL dotazu (sekvence switch), který potom určuje setřídění. Vypsané jméno souboru je zároveň odkazem na skript ke stažení souboru. Před názvem souboru je ještě vypsán znak „x“, který je odkazem pro smazání souboru. Smazání souboru je nutno potvrdit v dialogu, který je řešen JavaScriptem. Tím je také doplněna nápověda pro stahování souboru. Povšimněte si funkce Stripslashes, která je použita pro výpis komentáře souboru a také zaokrouhlení vypisované velikosti souboru (zobrazována v kB, údaj v databázi je vydělen konstantou 1024). Na konci skriptu můžeme ještě pomocí include zařadit formulář pro upload souborů.

Pro mazání souborů použijeme vdisk_delete.php:

<?php
$mess = ‚Nebyl určen soubor k odstranění!<br />‘;
if (!empty($_GET[‚file‘])) {
  $mess = ‚Soubor ‚.$_GET[‚file‘].‘ byl odstraněn.<br />‘;
  if (@MySQL_Query(„DELETE FROM „.$dbappname.“vdisk WHERE filename = ‚“.$_GET[‚file‘].“‚ LIMIT 1″))
  {
    if (!mysql_affected_rows())
    $mess=’Soubor ‚.$_GET[‚file‘].‘ nebyl nalezen!<br />‘;
    elseif (!@unlink($store_files.$_GET[‚file‘]))
      $mess = ‚Soubor ‚.$_GET[‚file‘].‘ byl vyjmut ze seznamu, ale nepodařilo se jej odstranit!<br />‘;
  }
  else
  $mess = ‚Soubor ‚.$_GET[‚file‘].‘ se nepodařilo vyjmout ze seznamu!<br />‘;
  }
echo $mess;
?>

Skript otestuje, zda je zadáno jméno souboru, který se má vymazat. Pokud je soubor zadán, odstraní se z databáze. Pokud proběhlo odstranění z databáze korektně, provede se vymazání souboru ze složky na serveru. Pokud proběhlo řádně i vymazání souboru ze složky, vypíše se na začátku skriptu připravené hlášení o bezchybném provedení. Pokud v některé části provádění selže, nastaví se chybové hlášení, skript je dále jen vypíše a ukončí se.

Ke stahování souborů slouží samostatný skript (narozdíl od předchozích se nevkládá do hlavního skriptu, je v kořeni stejně jako index.php) vdownload.php:

<?php
if (!empty($_GET[‚file‘]))
{
  require(‚handle/config.php‘);
  require(‚handle/opendb.php‘);
  $file_path=SubStr($_SERVER[‚SCRIPT_NAME‘], 0, StrRPos($_SERVER[‚SCRIPT_NAME‘],’/‘));
  $file_path.=’/‘.$store_files.$_GET[‚file‘];
  $file_path=’http://‘.$_SERVER[‚HTTP_HOST‘].$file_path;
  if (@MySQL_Query(„UPDATE „.$dbappname.“vdisk SET dloaded = dloaded+1 WHERE filename='“.$_GET[‚file‘].“‚ LIMIT 1″))
  {
    Header(„Location: $file_path“);
    Exit;
  }
  else
    echo ‚Došlo k chybě databáze!‘;
}
?>

Ověří se, je-li zadán soubor, který se má stáhnout. Pokud ano, zavede se potřebné nastavení a připojí se k databázovém serveru. Dále se získá absolutní cesta ke složce se soubory (je důležitá do hlavičky pro přesměrování) a v databázi se o 1 zvýší počet stažení souborů. Pokud proběhla práce s databází v pořádku (což také svědčí o tom, že požadovaný soubor je k dispozici), přesměrujeme prohlížeč na získanou absolutní cestu, ke které je přidána proměnná obsahující složku se soubory a jméno souboru ke stažení. Tento skript by bylo dobré poupravit tak, aby i při chybě odesílal do prohlížeče korektní XHTML kód – pro zjednodušení je toto ve skriptu vynecháno.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

1 komentář

  1. Victor Patrick

    Srp 12, 2023 v 10:57

    Jsem tak šťastný, že jsem narazil na tento článek, velmi posunul mé chápání na další nejvyšší úroveň. Skvělá práce a pokračujte v tom samém. Dave The Diver

    Odpovědět

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *