我有一个网站,用户必须付费才能下载他们在该网站上创建的视频。因此,我需要隐藏下载路径。
我有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);
这仍然不能正确下载。如果我没有脚本就直接下载文件,则可以正常工作。
答案 0 :(得分:0)
脚本看起来很不错。
根据评论,您似乎正在尝试从远程位置获取文件,功能filesize
不起作用,您必须找到获取文件大小或直接删除文件大小的另一种方法
一种获取文件大小的方法是通过标题
以下代码应从$nameOld
远程位置获取文件大小
$headers= get_headers($nameOld, 1);
$filesize = $headers['Content-Length'];
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);
如果任何人都可以提出更有效的代码示例,请继续。