前段时间用php写了1个通过aria2下载m3u8里面ts文件到本地的功能,因为没有实时显示进度,而且还需要打开PHP的shell_exec,可能会对系统安全存在风险,所以想有没有其他替代方法。
刚好这几天用到aria2配套的AriaNg,他是通过aria2的jsonrpc来实现的,所以想是不是也可以使用jsonrpc来下载。
以下是jsonrpc传值得标准基础格式,记录备忘。
//下面这个是单个文件下载的
{
"jsonrpc": "2.0",
"id": "这个可以自定义",
"method": "aria2.addUri",
"params":[
"token:这里写你aria2.conf里设置的rpc-secret",
["http://xxx.com/xxx.xx 这里写需要下载的文件地址"],
{"dir":"这里写需要下载的绝对路径,这一行可以不填,则默认下载到aria2.conf里设置的下载地址"}
]
}
//下面这个是多个文件下载的,就是把上面这个作为数组的元素就行了
[
{
"jsonrpc": "2.0",
"id": "这个可以自定义",
"method": "aria2.addUri",
"params":[
"token:这里写你aria2.conf里设置的rpc-secret",
["http://xxx.com/xxx.xx 这里写需要下载的文件地址"],
{"dir":"这里写需要下载的绝对路径,这一行可以不填,则默认下载到aria2.conf里设置的下载地址"}
]
},
{
"jsonrpc": "2.0",
"id": "这个可以自定义",
"method": "aria2.addUri",
"params":[
"token:这里写你aria2.conf里设置的rpc-secret",
["http://xxx.com/xxx.xx 这里写需要下载的文件地址"],
{"dir":"这里写需要下载的绝对路径,这一行可以不填,则默认下载到aria2.conf里设置的下载地址"}
]
}
]
<?php
$url = "http://127.0.0.1:6800/jsonrpc";
$data = '
{
"jsonrpc": "2.0",
"id": "这个可以自定义",
"method": "aria2.addUri",
"params":[
"token:这里写你aria2.conf里设置的rpc-secret",
["http://xxx.com/xxx.xx 这里写需要下载的文件地址"],
{"dir":"这里写需要下载的绝对路径,这一行可以不填,则默认下载到aria2.conf里设置的下载地址"}
]
}
';
echo postCurl($url,$data);
function postCurl($url,$data)
{
/**
if($type == 'json'){
$data = json_encode($data);//对数组进行json编码
$header= array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
}
**/
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_POST,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
if(!empty($data)){
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
}
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
//curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
$res = curl_exec($curl);
if(curl_errno($curl)){
echo 'Error+'.curl_error($curl);
}
curl_close($curl);
return $res;
}
?>
<script src="jquery-3.6.0.min.js"></script> <!--需要jquery支持-->
<script type="text/javascript">
var data = {
"jsonrpc": "2.0",
"id": "这个可以自定义",
"method": "aria2.addUri",
"params":[
"token:这里写你aria2.conf里设置的rpc-secret",
["http://xxx.com/xxx.xx 这里写需要下载的文件地址"],
{"dir":"这里写需要下载的绝对路径,这一行可以不填,则默认下载到aria2.conf里设置的下载地址"}
]
};
download_file(JSON.stringify(data)); //这里不能直接传json,需要转换成字符串
//执行下载
function download_file(data){
//console.log(data)
$.ajax({
url: "http://127.0.0.1:6800/jsonrpc",
data: data,
type: "post",
//async: false,//false为同步
dataType: "json",
success: function(obj) {
console.log(obj)
//这里放了ariang,添加jsonrpc之后,可以通过ariang查看下载进度,当然直接用ariang下载也方便,只是只能添加文件真实地址
location.href="ariang/index.html";
},
error:function (e) {
//返回500错误 或者其他 http状态码错误时 需要在error 回调函数中处理了 并且返回的数据还不能直接alert,需要使用
//$.parseJSON 进行转译 res.msg 是自己组装的错误信息通用变量
var res = $.parseJSON(e.responseText);
console.log(res);
}
});
}
</script>
这个最后可以通过http://xxx.com/xxx.php?name=xxx&m3u8=http://xxx.com/index.m3u8来传参执行
<?php
//aria2的jsonrpc地址
$aria_jsonrpc = "http://localhost:6800/jsonrpc";
if(isset($_GET['m3u8'])){
//获取url
$url = $_GET['m3u8'];
//获取网址域名
$urlarr = explode('/',$url);
$domain = $urlarr[0].'//'.$urlarr[2].'/';
$domain_dir = $urlarr[3].'/';
//先判断传入的m3u8里面有没有直接包含ts地址,还是套着一个m3u8文件
$url = Check_m3u8($url);
//定义m3u8名字,用于区分不同的m3u8,用自定义则获取,没有则通过网址里的信息来
$m3u8_name = $_GET['name']!=null && $_GET['name']!='' ? $_GET['name'] : $urlarr[3]."_".$urlarr[4];
//判断、新建tslist文件夹,用于存储
if(!file_exists('tslist/')){
mkdir('tslist/',0777);
}
//通过名称建立不同文件夹
$dir = 'tslist/'.$m3u8_name.'/';
$ts_dir = $dir.'ts/';
if(!file_exists($dir)){
mkdir($dir,0777);
}
if(!file_exists($ts_dir)){
mkdir($ts_dir,0777);
}
//获取m3u8文件里面的信息,并生成数组
$content = explode(chr(10),file_get_contents($url));
$i = 1;
//这个是用来单独存储ts文件真实网址的
$ts_url ='';
//这个是用来新建本地m3u8文件,保证路径与下载保存的ts文件路径一致
$m3u8_content = '';
$ts_url_json = '';
//通过循环来获取m3u8文件里每一行的信息
foreach ($content as $v){
//获取Key,并保存到本地,这个如果想完全本地播放m3u8的话是必须的
if(strstr($v,'.key')){
$get_key = explode('"',$v);
$key_url = $get_key[1];
//如不带域名,则添加,带了就保留
$key_urls = strstr($key_url,'http') ? $key_url : $domain.$key_url;
file_put_contents($dir.$m3u8_name.'_key.key',file_get_contents($key_urls));
//用于本地m3u8文件,key路径与m3u8文件在同一个文件夹
$m3u8_content .= $get_key[0].'"'.$m3u8_name.'_key.key"'.chr(10);
}
//获取正式ts文件网址
elseif(strstr($v,'.ts')){
//如不带域名,则添加,带了就保留 $domain_dir
$ts_urls = strstr($v,'http') ? $v : (strstr($v,'/') ? $domain.$v : $domain.$domain_dir.$v );
$ts_url .= $ts_urls.chr(10);
//获取ts文件名
$ts_name = explode('/',$v);
$m3u8_content .= 'ts/'.end($ts_name).chr(10);
$ts_url_json .= Add_to_Json($i,$ts_urls,$ts_dir);
$i++;
}
else{
$m3u8_content .= $v.chr(10);
}
}
file_put_contents($dir.$m3u8_name.'.m3u8',rtrim($m3u8_content,chr(10)));
//这个生成json文件,可忽略
file_put_contents($dir.$m3u8_name.'.json','['.rtrim($ts_url_json,',').']');
//赋值最终用于传给jsonrpc的json值
$ts_json = ('['.rtrim($ts_url_json,',').']');
echo 'http://'.$_SERVER['HTTP_HOST'].'/'.$dir.$m3u8_name.'.m3u8',"<br>";
//执行curl,这里放echo只为看是否成功
echo postCurl($aria_jsonrpc,$ts_json);
//如果你有ariang的话,就上面不echo,改为直接打开ariang页面查看
//echo '<script type="text/javascript">location.href="ariang/index.html";</script>';
}else{
echo "请传入m3u8地址,以?name=xxx&m3u8=http://xxxx.com/xxx.m3u8的方式";
}
//把ts地址拼接进aria2的jsonrpc支持的格式
function Add_to_Json($id,$tsurl,$ts_dir){
$json_str = '
{
"jsonrpc": "2.0",
"id": '.$id.',
"method": "aria2.addUri",
"params":[
"token:thisisaria2forsham",
["'.$tsurl.'"],
{"dir":"'.dirname(__FILE__).'/'.$ts_dir.'"}
]
},';
return $json_str;
};
//curl_post
function postCurl($url,$data)
{
/**
if($type == 'json'){
$data = json_encode($data);//对数组进行json编码
$header= array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
}
**/
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_POST,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
if(!empty($data)){
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
}
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
//curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
$res = curl_exec($curl);
if(curl_errno($curl)){
echo 'Error+'.curl_error($curl);
}
curl_close($curl);
return $res;
}
//判断m3u8里面有没有再包含m3u8文件
function Check_m3u8($url){
global $domain;
$m3u8_content = file_get_contents($url);
if(strstr($m3u8_content,'.m3u8')){
$m3u8_contents = explode(chr(10),$m3u8_content);
foreach($m3u8_contents as $m3u8){
if(strstr($m3u8,'.m3u8')){
$url = strstr($m3u8,'http') ? $m3u8 : $domain.$m3u8;
break;
}
}
Check_m3u8($url);
}
return $url;
}
?>