如何使用php

时间:2019-01-09 05:47:21

标签: php download http-headers mp4

我有一个网站,用户必须付费才能下载他们在该网站上创建的视频。因此,我需要隐藏下载路径。

我有php页面,其中的下载按钮是-

<form id="dl_script_form" action="dl-script.php" method="post" target="_blank">
<input name="userID" type="hidden" value="<?php echo $user->ID;?>" />
<input name="videosID" type="hidden" value="<?php echo $vId; ?>" />
<input name="downloadvids" id="downloadvids" type="submit" value="Download"/>
</form>

在dl-script.php上-

require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';

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

$nameOld = '/path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$nameNew = "download.mp4";
header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".filesize($nameOld));
readfile($nameOld);
exit(); 

当尝试单击提交时,开始下载(文件名为download.mp4),但是当我尝试在Windows Media Player中打开mp4时,它会告诉我-

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.

我已经检查了文件路径,并且能够在浏览器中播放视频或右键单击下载而没有问题。

因此,使用php脚本时,文件必须以某种方式损坏。我尝试添加/删除header content-*file_get_contents,但还是没有运气。

我在做什么错了?

编辑

出于测试目的,我修改了代码以从第二台服务器下载到运行脚本的原始服务器。

$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);

这仍然不能正确下载。如果我没有脚本就直接下载文件,则可以正常工作。

3 个答案:

答案 0 :(得分:0)

脚本看起来很不错。

根据评论,您似乎正在尝试从远程位置获取文件,功能filesize不起作用,您必须找到获取文件大小或直接删除文件大小的另一种方法

一种获取文件大小的方法是通过标题

以下代码应从$nameOld远程位置获取文件大小

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

get_headers() documentation

readfile()支持远程文件位置,但是allow_url_fopen php配置应打开


为了使其正常工作,您将必须找到相关的错误日志,如果错误报告是针对error_reporting=E_ALL的,则您下载的文件包含错误,因此,如果在文本编辑器中打开它,则将能够看到错误,否则请在您的error.log中搜索,其中有很大的变化,即allow_url_fopen的配置不正确,但是找到错误将帮助您解决问题。


编辑:

我已经测试了您的代码,可以从远程位置下载示例mp4

$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);

如果这不适用于您,则问题出在您的服务器设置中,可能是我之前提到的allow_url_fopen

答案 1 :(得分:0)

服务器端https处理是否会出现问题?您是否尝试过向第二个服务器发出普通的http请求?

您是否曾经考虑过使用安全网址?这可以帮助减少服务器上的网络和CPU负载。 您可以给用户一个临时链接,而不是隐藏真实的URL,该链接仅适用于他的IP(并在一段时间后过期)。这是大多数管站点所做的。 检查以下内容:http://nginx.org/en/docs/http/ngx_http_secure_link_module.html

答案 2 :(得分:0)

我无法通过这里的任何建议使它起作用,但是在继续深入研究之后,我得以使它起作用。

不过,唯一的问题是我必须将文件从第二台服务器保存到第一台服务器,才能进行下载。然后删除它,但是我很确定这不是有效的性能明智的选择。但是,我没有其他尝试过的工作。

起作用的关键是ob_start(), while (ob_get_level()) { ob_end_clean(); }

完整代码-

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);

如果任何人都可以提出更有效的代码示例,请继续。