1
votes

comment télécharger le fichier mp4 et masquer le chemin de l'url en utilisant php

J'ai un site sur lequel les utilisateurs doivent payer pour télécharger les vidéos qu'ils créent sur le site. Pour cette raison, je dois masquer le chemin des téléchargements.

J'ai la page php où se trouve le bouton de téléchargement -

$userid = $_POST['userID'];
$videosid = $_POST['videosID'];

$path = 'https://path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$save = '/var/path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';

file_put_contents($save, fopen($path, 'r'));

$nameNew = "download.mp4";

header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".filesize($save));
readfile($save);

Et sur le dl-script.php -

Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.


19 commentaires

Pour info, "cacher le chemin" est assez inutile si vous proposez une autre façon de télécharger le fichier. Ce que vous voulez, c'est une sorte de vérification des autorisations dans ce dl-script.php qui ne permet à un utilisateur de télécharger un fichier qu'une seule fois.


que voulez-vous dire si j'offre un moyen alternatif? C'est la seule façon dont ils sont censés pouvoir télécharger. Mon commentaire sur le clic droit est juste quelque chose que j'ai fait pour tester le fichier. Les utilisateurs ne doivent utiliser que le bouton de téléchargement mentionné. @deceze


Oui, bien sûr, mais cela ne «cache pas le fichier». C'est juste une autre façon d'obtenir le fichier. Pouvez-vous faire une demande spécifique à une URL spécifique et vous obtiendrez un fichier? → Oui → Pas «caché».


Ouais, mais cela n'expose pas l'URL aux utilisateurs qui ne sont pas «experts en technologie». Et surtout - sinon tous, mes utilisateurs ne le seront pas. Mon problème et la première étape pour le moment est d'obtenir le téléchargement du fichier correctement. Avez-vous une autre suggestion pour l'ensemble du processus mentionné dans la question et fournir une réponse?


J'essaierais de comparer le fichier téléchargé avec l'original pour voir quelle est la différence. Surtout les premiers octets sont probablement différents, voire rien.


le fichier a 0 octet


Eh bien, cela n’aide pas. Aucune erreur dans les journaux PHP / Apache?


J'ai trouvé cette erreur Avertissement PHP: filesize (): stat failed for https: .....


Montrez un exemple réel de $ nameOld .


https://example.com/path/to/01/007/video-001.mp4


N'utilisez pas d'URL, utilisez le chemin du fichier local. 😒


je ne peux pas car les fichiers sont hébergés sur mon deuxième serveur


Eh bien, voir stackoverflow .com / questions / 18073406 /… . Ou omettez simplement de sortir l'en-tête Content-Length.


lorsque je supprime la longueur du contenu, le fichier télécharge maintenant tous les octets mais ne fonctionne toujours pas. Est-ce qu'il me manque un autre en-tête?


Encore une fois, différez-le.


pour tester => essayez readfile sans en-têtes. Je pense qu'il doit y avoir une erreur que vos en-têtes cachent.


@AabirHussain il me montre le codage de la vidéo ..


@Rich J'essaie de reproduire votre cas sur ma machine ubuntu mais tout fonctionne bien. Une différence est le chemin que je pense que vous pouvez vérifier votre chemin le mien est => $ save = '/var/www/html/application/public/images/SAMPLE.mp4';


Un problème de taille pourrait être un problème de taille, vérifiez ceci => wordpress.stackexchange.com/questions/260381/...


3 Réponses :


0
votes

Les scripts semblent bien pour ce qu'ils font.

D'après les commentaires, il semble que vous essayez d'obtenir le fichier depuis un emplacement distant, la fonction filesize ne fonctionnerait pas, vous avez pour trouver un autre moyen d'obtenir la taille du fichier ou simplement de le supprimer

un moyen d'obtenir la taille du fichier est via les en-têtes

le code suivant devrait obtenir la taille du fichier de $ nameOld emplacement distant

$nameOld = 'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4';
$nameNew = "download.mp4";

$headers= get_headers($nameOld, 1);
$filesize = $headers['Content-Length'];

header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".$filesize);

readfile($nameOld);

documentation get_headers ()

readfile () prend en charge les emplacements de fichiers distants, mais la configuration php de allow_url_fopen doit être activée


Pour que cela fonctionne, vous devrez trouver le journal d'erreurs correspondant, si le rapport d'erreurs est à error_reporting = E_ALL alors le fichier que vous download contient l'erreur, donc si vous l'ouvrez dans un éditeur de texte, vous pourrez voir l'erreur, sinon recherchez dans votre error.log, il y a changements importants que le allow_url_fopen n'a pas été configuré correctement, mais trouver l'erreur vous aiderait à résoudre le problème.


Modifier:

J'ai testé votre code et il est possible de télécharger un exemple de mp4 depuis un emplacement distant

$headers= get_headers($nameOld, 1);
$filesize = $headers['Content-Length'];

si cela ne fonctionne pas pour vous, le problème se situe dans les paramètres de votre serveur, probablement le allow_url_fopen que j'ai déjà mentionné.


4 commentaires

@Rich a mis à jour ma réponse avec un exemple de test que j'ai exécuté pour vérifier que le code fonctionne. Le fichier téléchargé était en état de lecture.


J'ai vérifié les deux serveurs et allow_url_fopen est réglé sur «On» pour les deux. J'ai également copié et collé votre code et le téléchargement n'a toujours pas pu être ouvert et lu.


@ Rich pouvez-vous rendre votre rapport d'erreur plus détaillé, puis vous pouvez essentiellement voir quelle est l'erreur qui le fait échouer, sinon ce ne serait que deviner. si vous modifiez le rapport d'erreurs, vous pouvez supprimer l'en-tête Content-Type ou ouvrir le fichier téléchargé avec un éditeur de texte pour afficher son contenu (ou simplement vérifier le error.log)


que voulez-vous dire par rendre plus verbeux? Comment faire? Mon journal d'erreurs actuel n'affiche aucune erreur liée. Et l'ouverture du fichier affiche le texte / code du fichier.



0
votes

Cela pourrait-il être un problème avec la gestion https côté serveur? Avez-vous essayé une simple requête http vers le deuxième serveur?

Avez-vous déjà envisagé d'utiliser des URL sécurisées? Cela pourrait aider à réduire la charge du réseau et du processeur sur vos serveurs. Au lieu de masquer une URL réelle, vous pouvez donner un lien temporaire à l'utilisateur, qui ne fonctionne que pour son adresse IP (et expire après un certain temps). C'est ce que font la plupart des sites de tubes. Vérifiez ceci: http://nginx.org/en/docs/http/ngx_http_secure_link_module.html


0 commentaires

0
votes

Je n'ai pas pu le faire fonctionner avec aucune des suggestions ici, mais après avoir continué à creuser plus profondément, j'ai pu le faire fonctionner.

Le seul problème est que je dois enregistrer le fichier de mon second serveur sur mon premier serveur, pour que le téléchargement fonctionne. Je le supprime ensuite, mais je suis presque sûr que ce n'est pas efficace en termes de performances. Cependant, rien d'autre que j'ai essayé de travailler.

Le (s) élément (s) clé (s) qui l'ont fait fonctionner est ob_start (), while (ob_get_level ()) {ob_end_clean (); }

code complet -

ob_start();

$userid = $_POST['userID'];
$videosid = $_POST['videosID'];

$nameOld = 'https://path/to/get/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$save = '/path/to/save/it/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';

$nameNew = "download.mp4";

file_put_contents($save, fopen($nameOld, 'r'));

set_time_limit(0);

header('Connection: Keep-Alive');
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header("Content-Disposition: attachment; filename=$nameNew");
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($save));

      while (ob_get_level()) {
        ob_end_clean();
      }

readfile($save);
exit;

// delete file when done
unlink($save);

Si quelqu'un peut suggérer un exemple de code plus efficace, veuillez continuer.

p>


1 commentaires

Il semble que cette méthode enregistre également le fichier dans une mémoire temporaire. Êtes-vous sûr que cette méthode est meilleure en termes de performances d'E / S?