Autoriser le téléchargement d'un seul fichier.

Résolu/Fermé
Signaler
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
-
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
-
Bonjour à tous,

alors voilà je vous explique mon soucis :

j'héberge actuellement un site internet sur lequel je propose le téléchargement de documents, j'utilise comme page de téléchargement, une simple page .php avec laquelle je permets le listing d'un dossier complet (où les documents se trouvent), cependant ma demande est celle-ci, comment je pourrai et avec quel code je pourrai autoriser uniquement le téléchargement d'UN seul fichier, juste autoriser le téléchargement d'un seul et unique fichier une fois l'accès à la page autorisée (parmis tous les fichiers listés).

Merci de me venir en aide car la je stagne depuis un bon petit moment, merci beaucoup.

5 réponses

Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021
1 298
'lut,
une idée: lorsque tu donnes accès à la page avec le listing, tu génères un identifiant unique (par exemple 32 caractères
0-9A-Za-z
) que tu stockes en base de données et que tu passes en paramètre (idéalement GET) de la page de listing, par exemple
listing.php?key=GwPT6DpXf73rBfzpTiNgJXga4HAF9Eox
.
Dans la base (supposons SQL mais ça peut être du Mongo, Redis, ...), on voudra au minimum 2 colonnes pour l'exemple:
  • key
    ,
    varchar(32)
    , clé primaire ; chaîne de caractère unique que tu as généré
  • used
    ,
    bool
    , non-nul, défaut
    false
    ; si la clé a été utilisée = qu'un fichier a été téléchargé avec

Sur ta page de listing tu récupères ce paramètre via
$_GET['key']
et:
1. tu vérifies s'il existe bien dans ta base de données, si ce n'est pas le cas tu refuses l'accès au listing. Idem s'il existe mais que
used == true
, cas où un fichier a déjà été téléchargé
2. tu ajoutes ce paramètre aux liens proposés:
download.php?file=abcdef&key=GwPT6DpXf73rBfzpTiNgJXga4HAF9Eox
.
Du coté de ta page de téléchargement ("download.php"), toujours avec
$_GET['key']
:
1. comme pour le listing, tu vérifies s'il existe bien dans ta base de données, si ce n'est pas le cas tu refuses l'accès au fichier
2. tu vérifies si
used == true
, si c'est le cas tu refuses le téléchargement et dit qu'un fichier a déjà été téléchargé
3. sinon, tu envoies le fichier et passes
used
à
true
.

C'est qu'un exemple rapide. Il serait plus propre de stocker l'identifiant du fichier téléchargé au lieu d'un simple booléen.
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3
Si je fais comme ça la personne pourra avoir accès au lien direct ^^

J'utilise ce script là :

<?php
$dir_nom = '.'; // dossier listé (pour lister le répertoir courant : $dir_nom = '.' --> ('point')
$dir = opendir($dir_nom) or die('Erreur de listage : le répertoire n\'existe pas'); // on ouvre le contenu du dossier courant
$fichier= array(); // on déclare le tableau contenant le nom des fichiers
$dossier= array(); // on déclare le tableau contenant le nom des dossiers

while($element = readdir($dir)) {
if($element != '.' && $element != '..' && strrchr($element,'.') != '.php') {
if (!is_dir($dir_nom.'/'.$element)) {$fichier[] = $element;}
else {$dossier[] = $element;}
}
}

closedir($dir);

if(!empty($dossier)) {
sort($dossier); // pour le tri croissant, rsort() pour le tri décroissant
echo "Liste des dossiers accessibles dans '$dir_nom' : \n\n";
echo "\t\t<ul>\n";
foreach($dossier as $lien){
echo "\t\t\t<li><a href=\"$dir_nom/$lien \">$lien</a></li>\n";
}
echo "\t\t</ul>";
}

if(!empty($fichier)){
sort($fichier);// pour le tri croissant, rsort() pour le tri décroissant

echo "\t\t<ul>\n";
foreach($fichier as $lien) {
echo "\t\t\t<li><a href=\"$dir_nom/$lien \">$lien</a></li>\n";
}
echo "\t\t</ul>";
}
?>

<?php
// Déclaration des variables
$ident=$idp=$ids=$idd=$codes=$code1=$code2=$code3=$code4=$code5=$datas=''; 
$idp = XXXXX; 
// $ids n'est plus utilisé, mais il faut conserver la variable pour une question de compatibilité
$idd = XXXXX; 
$ident=$idp.";".$ids.";".$idd;
// On récupère le(s) code(s) sous la forme 'xxxxxxxx;xxxxxxxx'
if(isset($_POST['code1'])) $code1 = $_POST['code1']; 
if(isset($_POST['code2'])) $code2 = ";".$_POST['code2']; 
if(isset($_POST['code3'])) $code3 = ";".$_POST['code3']; 
if(isset($_POST['code4'])) $code4 = ";".$_POST['code4']; 
if(isset($_POST['code5'])) $code5 = ";".$_POST['code5']; 
$codes=$code1.$code2.$code3.$code4.$code5; 
// On récupère le champ DATAS
if(isset($_POST['DATAS'])) $datas = $_POST['DATAS']; 
// On encode les trois chaines en URL
$ident=urlencode($ident);
$codes=urlencode($codes);
$datas=urlencode($datas);

/* Envoi de la requête vers le serveur StarPass
Dans la variable tab[0] on récupère la réponse du serveur
Dans la variable tab[1] on récupère l'URL d'accès ou d'erreur suivant la réponse du serveur */
$get_f=@file( "http://script.starpass.fr/check_php.php?ident=$ident&codes=$codes&DATAS=$datas" ); 
if(!$get_f) 
{ 
exit( "Votre serveur n'a pas accès au serveur de StarPass, merci de contacter votre hébergeur. " ); 
} 
$tab = explode("|",$get_f[0]);

if(!$tab[1]) $url = "http://script.starpass.fr/error.php"; 
else $url = $tab[1]; 

// dans $pays on a le pays de l'offre. exemple "fr"
$pays = $tab[2]; 
// dans $palier on a le palier de l'offre. exemple "Plus A"
$palier = urldecode($tab[3]); 
// dans $id_palier on a l'identifiant de l'offre
$id_palier = urldecode($tab[4]); 
// dans $type on a le type de l'offre. exemple "sms", "audiotel, "cb", etc.
$type = urldecode($tab[5]); 
// vous pouvez à tout moment consulter la liste des paliers à l'adresse : [http://script.starpass.fr/palier.php]

// Si $tab[0] ne répond pas "OUI" l'accès est refusé
// On redirige sur l'URL d'erreur
if( substr($tab[0],0,3) != "OUI" ) 
{ 
       header( "Location: $url" ); 
       exit; 
} 
else 
{ 
       /* Le serveur a répondu "OUI" 

       On place un cookie appelé CODE_BON et qui vaut la valeur 1 
       Ce cookie est valide jusqu'à ce que l'internaute ferme son navigateur 
       Dans les pages suivantes, nous testerons l'existence du cookie 
       S'il existe, c'est que l'internaute est autorisé, 
       sinon on le renverra sur une page d'erreur */ 
       setCookie( "CODE_BON", "1", 0 ); 
       // Si vous avez plusieurs documents, nommer le cookie plutôt 'code'+iDocumentId 

       // vous pouvez afficher les variables de cette façon : 
       // echo "idd : $idd / codes : $codes / datas : $datas / pays : $pays / palier : $palier / id_palier : $id_palier / type : $type"; 
} 
?>
Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021
1 298
Tu aurais du dire dès le départ que tu utilisais un service comme StarPass (que je hais infiniment, mais bon).
Ce code est non seulement peu lisible (manque d'indentation), il est aussi dangereusement troué au niveau sécurité: la validation passe par un cookie, ce qui est stocké coté client. J'ai juste a créer un cookie CODE_BON à 1 dans mon navigateur avec les outils de développement et hop je prend tous tes fichiers. Le contact de starpass se fait par HTTP, donc pas moyen de vérifier l'authenticité de la réponse.
Les 2 parties de ce code sont sur la même page?
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3 >
Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021

Oui elles sont sur la page de paiement et sur la page de téléchargement...
Ce sont les méthodes fournies par Starpass lol
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3
up :)
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3
Bonjour,

Merci pour votre réponse, oui j'en ai bien pris part et je vous en remercie, cependant ce n'est pas vraiment ce que je recherche, actuellement le visiteur procède au paiement, ensuite, il est redirigé vers la fameuse page où il doit sélectionner son fichier, le problème c'est que la page reste ouverte et il peut avoir accès à tous les autres fichiers si vous avez une piste je vous en serai très reconnaissant merci.
Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021
1 298
Un peu de réflexion de ta part t'aurais permis d'adapter mon exemple à ton cas de figure. Le but de CCM n'est pas de pondre du code tout chaud prêt à l'emploi, c'est d'aider à la compréhension et la résolution de problèmes.
Gardes ton code de contact de StarPass, mais au lieu du
setCookie( "CODE_BON", "1", 0 );
, fais ce que je t'ai suggéré: création d'un ID unique, stocké en base, et redirection vers ta page avec cet ID en paramètre. À toi de voir comment tu gères la base de données. Tu peux aussi t'en passer complètement et t'appuyer sur un cookie chiffré et signé comme un JWT par exemple.
Je ne vois pas pourquoi tu mentionnes "Si je fais comme ça la personne pourra avoir accès au lien direct", vu que cette page de listing est celle qui est censé être protégée. Le seul lien direct qui doit être accessible, c'est ce qu'il y a avant cette page, potentiellement le même listing mais sans lien d'accès, ou juste un aperçu.
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3
up svp
Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021
1 298
Pourquoi "up" ? Tu t'attends à d'autres solutions que ce que je te propose ?
Il n'y en aura, dans l'idée, pas d'autre. Ton problème est simple et je ne vois qu'une seule manière de le décrire: tu as une page demandant paiement pour protéger les ressources qui sont derrière. Tu veux t'assurer qu'une unique ressource soit téléchargeable parmi celles proposées, il faut donc, et c'est le principe de base de toute solution qui te sera proposée ici comme ailleurs, pouvoir faire le lien entre un paiement et le téléchargement ou non d'un fichier.
Une fois la capacité technique de faire ce lien conçue, il faudra t'en servir pour déterminer, avant le potentiel envoi de fichier, si le paiement a déjà été utilisé ou non.
Ce que je n'ai pas expliqué clairement, que tu n'as pas compris, et que je viens juste de réaliser que tu ne comprends pas (d'où ton "Si je fais comme ça la personne pourra avoir accès au lien direct"), c'est que nulle part dans ce processus tu ne dois donner de lien direct vers une ressource non protégée. Tes fichiers originaux doivent être inaccessibles depuis le web ; sur un hébergement avec Apache tu peux te servir des fichiers
.htaccess
pour empêcher l'accès. C'est la page PHP "
download.php
" qui va, une fois la pré-condition de téléchargabilité validée, envoyer le fichier en le lisant depuis le disque, en spécifiant au préalable type, nom, taille du fichier dans les en-têtes HTTP, puis en envoyant le contenu:
$filename = VARIABLE CONTENANT LE CHEMIN DU FICHIER;

$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: ' . finfo_file($finfo, $filename));
finfo_close($finfo);
header('Content-Disposition: attachment; filename='.basename($filename));

// Pas de mise en cache
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');

header('Content-Length: ' . filesize($filename));

ob_clean();
flush();
readfile($filename);
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3 >
Messages postés
4764
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
5 octobre 2021

Merci de ta réponse je suis bloqué pour une dernière chose après ce sera choses faite :)
j'utilise ce script php qui fonctionne à merveille grâce à tes conseils :

<?php
$file = '/var/www/wordpress/wp-content/themes/insight/DossierInfo/'.$_POST['dossierInf'].'.pdf';
 
if (file_exists($file)) {
    header("Content-type: application/force-download");
    header('Content-Disposition: attachment; filename='.$file);
    readfile($file);
    exit;
} else {
echo "Le fichier $file n'existe pas.";
}
?>


EDIT : Correction des balises de code


Par contre j'aimerai redirigé la personne sur une autre page du genre merci pour votre commande, je n'ai trouvé aucune autre méthode même en javascript cela ne fonctionne plus :/ aurais-tu une solution s'il te plaît ? Merci
Messages postés
34265
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
9 décembre 2021
3 870 >
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019

Bonjour,

Nouvelle question = ouverture d'une nouvelle discussion !
Merci de penser à mettre celle la en résolue ( via l'icone de roue crantée qui se situe en haut, à droite du titre de ta question ).


NB: Les "UP" à répétition sont mal vus.... évite !
Merci.
Messages postés
99
Date d'inscription
dimanche 18 janvier 2009
Statut
Membre
Dernière intervention
1 septembre 2019
3
Mon code HTML supprimé alors que je n'ai rien demandé, alors que la form fait partie du code, merci beaucoup...