jeudi, novembre 21, 2024
Nom d'utilisateur : Mot de passe :
Home > Dossiers > Dossiers PHP > Téléchargement de fichiers via PHP
[NEWS]
Envoyé par unreal
Il arrive souvent à ce qu'on souhaite proposer des fichiers à télécharger sur un site. Pour cela, il existe plusieurs solutions selon le niveau de protection des fichiers dont on a besoin.

Solution simplicite

Il s'agit simplement d'une redirection dont la seule utilité c'est compter le nombre de téléchargements (pour l'afficher sur le site).

La méthode classique consiste alors à programmer un download.php qui acceptera comme paramètre l'ID du fichier ou le path vers le fichier.

Exemple d'implémentation.

download.php
<?php

$p = '';
if (isset($_GET['p']))
$p = $_GET['p'];

if ($p) {
// On n'autorise pas les chemins '..'
if (preg_match('/\.\./', $p)) {
Header ('Location: ./');
exit();
}

// Code pour mettre a jour
// les stats de telechargements

Header ('Location: ./files'.$p);
} else {
Header ('Location: ./');
}
?>


Même si la détection du '..' n'est pas vraiment nécessaire dans ce cas précis (vu que la redirection ne donnera aucunement accès à des fichiers en dehors du www_root du serveur Web), cela reste une bonne pratique. Et c'est une bonne idée d'adopter les bonnes pratiques dès le début. happy.gif

L'inconvénient de cette méthode c'est qu'il est facile de connaître l'adresse réelle du fichier, donc il est possible de contourner download.php. Si le but de download.php est seulement de générer des statistiques de téléchargements, ceci n'est guère un problème. Par contre, pour sécuriser les fichiers, il va falloir faire mieux.


Solution sécurisée

Avec cette méthode, il n'est plus question de placer les fichiers à télécharger dans le www_root et de réaliser une redirection, mais d'envoyer les données à travers download.php.

L'exemple qui suit montre une implémentation (parmi d'autres).

download.php
<?php
$UploadDir = '/path/to/download/folder'; // Pas de / final !

$p = '';
if (isset($_GET['p']))
$p = $_GET['p'];

if ($p) {
// On n'autorise pas les chemins '..'
if (preg_match('/\.\./', $p)) {
Header ('Location: ./');
exit();
}

// Code pour mettre a jour
// les stats de telechargements

// Code pour gerer les droits d'acces

$path = $UploadDir . $p;

if (!is_file($path))
exit();

@ob_end_clean();
@ini_set('zlib.output_compression', 'Off');

header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header('Content-Disposition: attachment; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));

$handle = fopen($path, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();

} else {
Header ('Location: ./');
}
?>


Quelques remarques :
  • La détection '..' est particulièrement importante ici, sans quoi il serait possible d'accéder à tous les fichiers du disque.
  • Si après vérification l'utilisateur n'a pas les droits nécessaires, il suffit de quitter (exit();) ou de renvoyer sur une autre page (Header ('Location: page.php');).
  • Cette implémentation charge le fichier par bloc de 8ko -- ceci est important car il n'est pas concevable de charger entièrement le fichier à télécharger en mémoire.


Voilà c'est fini, à vous de jouer maintenant. happy.gif

Posté le 12/07/05 à 19:47

Commentaires...[1-2]


RE: Téléchargement de fichiers via PHP
idrisdodo@yahoo.fr
Bonjour,

Pour info, download=télécharger, path=chemin, file=fichier. On se comprendra mieux si on utilise la même langue. : )

Juste une question : j'ai un site sur lequel beaucoup de téléchargements sont effectués (plusieurs par minute) et j'ai l'impression que cette méthode confond les fichiers entre les différents téléchargements. En effet, plusieurs personnes me parlent de fichiers corrompus. Pourtant quand je teste (sur différents navigateurs), il n'y a aucun souci.

Un avis ?

Posté le 25/08/06 à 16:48

RE: Téléchargement de fichiers via PHP

unreal

[AVATAR]

Messages : 15
Inscrit le : 07/03/04
idrisdodo@yahoo.fr a dit :
Juste une question : j'ai un site sur lequel beaucoup de téléchargements sont effectués (plusieurs par minute) et j'ai l'impression que cette méthode confond les fichiers entre les différents téléchargements. En effet, plusieurs personnes me parlent de fichiers corrompus. Pourtant quand je teste (sur différents navigateurs), il n'y a aucun souci.

Un avis ?


Il ne devrait pas avoir de confusion entre les fichiers vu que chaque téléchargement va créer au nouveau thread/processus au niveau du serveur Web. Par contre, j'imagine que si vos visiteurs utilisent des logiciels d' "accélération" de téléchargement (getright...) il peut avoir des soucis vu que ces logiciels lancent plein de connexions sur un serveur qui ne supporte pas le resume.

Donc, je pense qu'il vous faudra modifier le script pour supporter le resume ou détecter des tentatives de resume et balancer une erreur http genre 403.

En tout cas, n'hésitez pas à reposter ici si vous réglez le problème. happy.gif

Message édité par unreal le 29/08/06 à 09:49

Posté le 29/08/06 à 09:45

Téléchargement de fichiers via PHP
Vous pourriez commenter si vous aviez un compte !