[PHP]Envoyer une fichier à un utilisateur sans lui donner l'adresse

Envoyer une fichier à un utilisateur sans lui donner l'adresse [PHP] - PHP - Programmation

Marsh Posté le 26-01-2011 à 08:56:13    

Bonjour a tous.
 
Je tiens un site web dans lequel il y a une partie nécessitant un couple identifiant/mot de passe. Cet accès, je voudrais le faire payant; et il donnera droit à télécharger des fichiers (rien d'illégal, je précise tout de même). Donc, je voudrais pouvoir envoyer mes fichiers aux utilisateurs sans qu'ils puissent voir l'adresse; sinon il suffit que quelqu'un conaisse l'adresse du fichier et la donne a tout le monde.
 
Pour le moment, j'ai utilisé cela (inspiré de la phpdoc)
[php]  //Envoi du fichier
  ob_clean();
  flush();
  header('Content-Description: File Transfer');
  header('Content-Type: application/octet-stream');
  header('Content-Disposition: attachment; filename="' . $file . '"');
  header("Content-type: application/force-download" );
  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($path . '/' . $file));
  readfile($path . '/' . $file);
[/php]
 
Ca fonctionne, mais il faut du temps pour que le serveur commence à envoyer le fichier quand ce dernier est assez lourd (du genre 10mo). Qui plus est, l'utilisateur ne sait rien faire d'autre sur le site tant que le téléchargement n'est pas terminé; et enfin; ca ne fonctionne pas sous opera mini avec mon GSM.
J'avais pensé à copier le fichier dans un répertoire temporaire puis donner l'adresse, mais ça deviendra vite ingérable.
 
Avez vous d'autres idées? Merci d'avance.

Reply

Marsh Posté le 26-01-2011 à 08:56:13   

Reply

Marsh Posté le 26-01-2011 à 09:40:43    

Apache est peut-être pas bien configuré non plus...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 26-01-2011 à 10:14:19    

Matth002 a écrit :


J'avais pensé à copier le fichier dans un répertoire temporaire puis donner l'adresse, mais ça deviendra vite ingérable.


 
Pourquoi ingérable ? C'est une solution qui est souvent employée et qui laisse la possibilité de reprendre le d/l si ça plante au milieu.
 
Avec un simple CRON qui efface les fichiers anciens (selon une durée que tu définis), c'est une solution qui vaut la tienne mais qui ne charge pas le serveur puisque c'est apache qui envoie les fichier sans passer par PHP.

Reply

Marsh Posté le 26-01-2011 à 10:36:26    

+1
Y a pas 36'000 manières de s'y prendre ... soit tu passes direct par les sockets via readfile, soit tu lui poses ça dans un rep temporaire..
 
Le seul "hic" avec les rep temporaires c'est que si tu mets un cron trop court que le mec a une bande passante de merde, ça va planter. Au contraire, si tu mets un cron trop long tu risques que les liens commencent à se balader (ou de saturer ton HDD).


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 26-01-2011 à 10:45:37    

Merci pour vos réponses.
 
Ce que je n'aime pas trop avec l'histoire de copier les fichiers, c'est que si le site devient populaire, le DD va passer son temps à gratter...
 
Est-ce qu'il y aurait moyen de "multithreader" le readfile? Je veux dire lancer une instance du script qui fait le readfile, mais permettre à l'utilisateur de continuer d'utiliser le site?
 
Et avec le readfile, pourquoi est-ce qu'il y a un délai avant qu'il commence a envoyer le fichier? UN délai de 1sec pour 10mo ne me dérange pas, mais là on est de l'ordre de la dizaine de seconde... Sans compter qu'il y a aussi un délai après la réception complete du fichier. Pourtant j'ai bien précisé la taille de ce dernier...
 
PS: Je vais quand même jeter un oeil du côté du CRON voir ce qui existe :) Merci pour le toyo

Reply

Marsh Posté le 26-01-2011 à 11:10:56    

-Quand ton site sera populaire, tu pourras utiliser des solutions style memcached pour limiter les accès HDD.
- Ouvre la dans une nouvelle page (pas le choix)
- C'est le temps qu'il faut pour que apache load le tout probablement


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 26-01-2011 à 13:00:43    

Je vais essayer de faire ca avec une nouvelle page, merci :)

Reply

Marsh Posté le 27-01-2011 à 16:17:33    

SAlut!
 
Je n'ai malheureusement pas réussi à résoudre mon problème avec le readfile et une nouvelle page: le site est toujours bloqué pendant le téléchargement. J'ai utilisé un autre script, donné en exemple dans la doc, mais rien a faire.
 

Code :
  1. //Ajout de l'information de download
  2.   $downloaded = $sql_file['downloaded'] + 1;
  3.   $sql_download -> sql_update(array('id' => $_GET['id_file']), array('downloaded' => $downloaded), $parameters['table']);
  4.   //Récupération du type
  5.   $mtime = ($mtime = filemtime($path . '/' . $file)) ? $mtime : gmtime();
  6.   $size = intval(sprintf("%u", filesize($path . '/' . $file)));
  7.   //Désactivation de la compression
  8.   @apache_setenv('no-gzip', 1);
  9.   @ini_set('zlib.output_compression', 0);
  10.   //Envoi des header
  11.   header("Content-type: application/force-download" );
  12.   header('Content-Type: application/octet-stream');
  13.   if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE" ) != false)
  14.    header("Content-Disposition: attachment; filename=" . urlencode(basename($path . '/' . $file)) . '; modification-date="' . date('r', $mtime) . '";');
  15.   else
  16.    header("Content-Disposition: attachment; filename=\"" . basename($path . '/' . $file) . '"; modification-date="' . date('r', $mtime) . '";');
  17.   header('Content-Length: ' . $size);
  18.   //Empecher les soucis avec de larges fichiers
  19.   set_time_limit(300);
  20.   // Cas de grands fichiers
  21.   $chunksize = 1 * (1024 * 1024); // how many bytes per chunk
  22.   if ($size > $chunksize) {
  23.     $handle = fopen($path . '/' . $file, 'rb');
  24.     $buffer = '';
  25.     while (!feof($handle)) {
  26.    $buffer = fread($handle, $chunksize);
  27.    echo $buffer;
  28.    ob_flush();
  29.    flush();
  30.     }
  31.     fclose($handle);
  32.   } else {
  33.     readfile($path . '/' . $file);
  34.   }
  35.   exit;
  36.  }


 
Une autre idée pour réussir à ne pas bloquer tout le site pendant le téléchargement? Un autre soucis est que une fois le téléchargement terminé, le navigateur continue de recevoir des données (dans chrome, le truc de téléchargement vert continue de tourner), alors qu'il a tout reçus... Sous firefox 4b10, même soucis. (il reste bloqué sur quelques secondes restantes pendant environ 15-20sec)

Reply

Marsh Posté le 27-01-2011 à 16:18:12    

Mais qu'est-ce que tu entends par "bloquer tout le site" ?


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 27-01-2011 à 17:16:48    

ben pendant le téléchargement, si j'essaye de retourner sur le site pour visiter une autre page, il ne se passe rien. Le brouteur charge la page (on voit l'animation), mais elle ne se charge effectivement qu'une fois le téléchargement terminé.
 
Par contre, deux utilisateurs différents peuvent heureusement vister le site sans avoir ce soucis si l'un des deux télécharge.
 
C'est comme si php refusait d'exécuter quoique ce soit d'autre tant qu'il n'a pas terminé le readfile pour chaque utilisateur.

Reply

Marsh Posté le 27-01-2011 à 17:16:48   

Reply

Marsh Posté le 27-01-2011 à 17:56:15    

Si t'es sous Windows, c'est "normal", apache a beaucoup de mal à gérer les requêtes multiples. Sous Linux, devrait pas y avoir de pbs. Là, ton pb vient de la conf du serveur, je pense...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 27-01-2011 à 18:55:38    

Je suis sous linux. Pour la conf serveur, c'est pas vraiment moi qui m'en occupe, mais un amis. Il s'y connais assez en linux, mais n'a pas vraiment l'habitude des configurations de serveurs, de même que moi même. On essaye d'adapter comme on peut...
 
Ici, que faudrait-il modifier? ou du moins de quel côté dois-je chercher?

Reply

Marsh Posté le 27-01-2011 à 21:26:09    

Et sinon, un système de cache, mais avec des liens virtuels, pour ne pas multiplier les fichiers ? ( Attation, sa ne marche que pour un serveur linusk... )


---------------
Fort et motivé. Sauf parfois.
Reply

Marsh Posté le 27-01-2011 à 21:57:58    

Ca me parait compliqué tout ça...
 
Il doit quand même bien y avoir moyen de faire un readfile proprement non? C'est quand même la solution qui me semble la plus appropriée, efficace et simple d'implémentation...

Reply

Marsh Posté le 27-01-2011 à 22:15:11    

Bah faut que tout le fichier soit lu, et mis en ram par php avant d'être envoyé...
C'est pas ce que je trouve propre. Surtout que si tu veut faire télécharger un fichier > 10mo, faut changer les paramêtres de php. Si en face ya pas assez de BP, faut augmenter le temps max d'execution d'un script de manière démesurée...


---------------
Fort et motivé. Sauf parfois.
Reply

Marsh Posté le 28-01-2011 à 17:19:05    

Ce que je veux dire, c'est qu'il doit bien y avoir moyen simple de lire quelques bits du fichiers, l'envoyer par le socket, attendre accusé, et recommencer l'opération jusqu'a la fin... non? Un peu comme on ferais en java par exemple.

Reply

Marsh Posté le 28-01-2011 à 17:36:12    

pourquoi tu fais pas un lien unique en jouant avec la session ?

Reply

Marsh Posté le 07-02-2011 à 10:33:13    

Matth002 a écrit :

Ce que je veux dire, c'est qu'il doit bien y avoir moyen simple de lire quelques bits du fichiers, l'envoyer par le socket, attendre accusé, et recommencer l'opération jusqu'a la fin... non? Un peu comme on ferais en java par exemple.


Oui on peut streamer en PHP...
 
Suffit de faire fopen('php://output') pour accéder a la sortie PHP via un stream, et de faire un steam_copy_to_stream du fichier à la sortie PHP.
( http://www.php.net/manual/fr/funct [...] stream.php )


---------------
| AMD Ryzen 7 7700X 8C/16T @ 4.5-5.4GHz - 64GB DDR5-6000 30-40-40 1T - AMD Radeon RX 7900 XTX 24GB @ 2680MHz/20Gbps |
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed