diff --git a/README.md b/README.md index a10a7d1d..e3a1f367 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Cloudreve - Make the cloud easy for everyone * 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、自建远程服务器,当然,还有本地存储 * 可限制单文件最大大小、MIMEType、文件后缀、用户可用容量 +* 基于Aria2的离线下载 * 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览 * 移动端全站响应式布局 * 文件、目录分享系统,可创建私有分享或公开分享链接 diff --git a/application/index/controller/Admin.php b/application/index/controller/Admin.php index f7380f13..0a2c52f5 100644 --- a/application/index/controller/Admin.php +++ b/application/index/controller/Admin.php @@ -248,6 +248,10 @@ class Admin extends Controller{ return $this->adminObj->saveMailSetting(input('post.')); } + public function SaveAria2Setting(){ + return $this->adminObj->saveAria2Setting(input('post.')); + } + public function SendTestMail(){ return $this->adminObj->sendTestMail(input('post.')); } @@ -482,5 +486,32 @@ class Admin extends Controller{ 'policy' => $this->adminObj->getAvaliablePolicy(), ]); } + + public function RemoteDownload(){ + $this->adminObj->listDownloads(); + return view('download', [ + 'options' => $this->siteOptions, + 'optionsForSet' => Option::getValues(["aria2"]), + 'list' => $this->adminObj->pageData, + 'originList' => $this->adminObj->listData, + 'pageNow' => $this->adminObj->pageNow, + 'pageTotal' => $this->adminObj->pageTotal, + 'dataTotal' => $this->adminObj->dataTotal, + ]); + } + + public function CancelDownload(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new \app\index\model\Aria2($aria2Options); + $downloadItem = Db::name("download")->where("id",input("post.id"))->find(); + if(empty($downloadItem)){ + return json(['error'=>1,'message'=>"未找到下载记录"]); + } + if($aria2->Remove($downloadItem["pid"],"")){ + return json(['error'=>0,'message'=>"下载已取消"]); + }else{ + return json(['error'=>1,'message'=>"取消失败"]); + } + } } diff --git a/application/index/controller/Home.php b/application/index/controller/Home.php index 5f9f78c8..f73650c0 100644 --- a/application/index/controller/Home.php +++ b/application/index/controller/Home.php @@ -38,6 +38,16 @@ class Home extends Controller{ ]); } + public function Download(){ + $userInfo = $this->userObj->getInfo(); + $groupData = $this->userObj->getGroupData(); + return view('download', [ + 'options' => Option::getValues(['basic','group_sell']), + 'userInfo' => $userInfo, + 'groupData' => $groupData, + ]); + } + public function Album(){ $userInfo = $this->userObj->getInfo(); $list = Db::name("files")->where("upload_user",$this->userObj->uid) @@ -60,7 +70,7 @@ class Home extends Controller{ $listData = $list->all(); $pageNow = input("?get.page")?input("get.page"):1; if($pageNow>$pageCount){ - $this->error('页面不存在',404,Option::getValues(['basic','group_sell'])); + $this->error('您当前没有上传任何图片',404,Option::getValues(['basic','group_sell'])); } return view('album', [ 'options' => Option::getValues(['basic','group_sell']), diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php index 04201747..e16a1c53 100644 --- a/application/index/controller/RemoteDownload.php +++ b/application/index/controller/RemoteDownload.php @@ -29,16 +29,19 @@ class RemoteDownload extends Controller{ return true; } - private function insertRecord($aria2,$url){ + private function insertRecord($aria2,$url,$path){ Db::name("download")->insert([ "pid" => $aria2->pid, "path_id" => $aria2->pathId, "owner" => $this->userObj->uid, - "save_dir" => 1, + "save_dir" => $path, "status" => "ready", "msg" => "", "info"=>"", "source" =>$url, + "file_index" => 0, + "is_single" => 1, + "total_size" => 0, ]); } @@ -51,9 +54,36 @@ class RemoteDownload extends Controller{ $aria2 = new Aria2($aria2Options); $downloadStart = $aria2->addUrl(input("post.url")); if($aria2->reqStatus){ - $this->insertRecord($aria2,input("post.url")); + $this->insertRecord($aria2,input("post.url"),input("post.path")); + return json(["result"=>['success'=>true,'error'=>null]]); }else{ - return json(['error'=>1,'message'=>$aria2->reqMsg]); + return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]); + } + } + + public function AddTorrent(){ + $policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find(); + if(!$this->checkPerimission(0) || $policyData["policy_type"] != "local"){ + return json(['error'=>1,'message'=>'您当前的无用户无法执行此操作']); + } + $downloadingLength = Db::name("download") + ->where("owner",$this->userObj->uid) + ->where("status","<>","complete") + ->where("status","<>","error") + ->where("status","<>","canceled") + ->sum("total_size"); + if(!\app\index\model\FileManage::sotrageCheck($this->userObj->uid,$downloadingLength)){ + return json(["result"=>['success'=>false,'error'=>"容量不足"]]); + } + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $torrentObj = new \app\index\model\FileManage(input("post.id"),$this->userObj->uid,true); + $downloadStart = $aria2->addTorrent($torrentObj->signTmpUrl()); + if($aria2->reqStatus){ + $this->insertRecord($aria2,input("post.id"),input("post.savePath")); + return json(["result"=>['success'=>true,'error'=>null]]); + }else{ + return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]); } } @@ -69,4 +99,81 @@ class RemoteDownload extends Controller{ } } + public function FlushUser(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $toBeFlushed = Db::name("download") + ->where("owner",$this->userObj->uid) + ->where("status","<>","complete") + ->where("status","<>","error") + ->where("status","<>","canceled") + //取消的 + ->select(); + foreach ($toBeFlushed as $key => $value) { + $aria2->flushStatus($value["id"],$this->userObj->uid,$this->userObj->getPolicy()); + } + } + + public function Cancel(){ + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $downloadItem = Db::name("download")->where("owner",$this->userObj->uid)->where("id",input("post.id"))->find(); + if(empty($downloadItem)){ + return json(['error'=>1,'message'=>"未找到下载记录"]); + } + if($aria2->Remove($downloadItem["pid"],"")){ + return json(['error'=>0,'message'=>"下载已取消"]); + }else{ + return json(['error'=>1,'message'=>"取消失败"]); + } + } + + public function ListDownloading(){ + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","in",["active","ready","waiting"])->order('id desc')->select(); + foreach ($downloadItems as $key => $value) { + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $downloadItems[$key]["fileName"] = basename($connectInfo["dir"]); + $downloadItems[$key]["completedLength"] = $connectInfo["completedLength"]; + $downloadItems[$key]["totalLength"] = $connectInfo["totalLength"]; + $downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name"); + }else{ + $downloadItems[$key]["fileName"] = $value["source"]; + } + $downloadItems[$key]["completedLength"] = 0; + $downloadItems[$key]["totalLength"] = 0; + $downloadItems[$key]["downloadSpeed"] = 0; + } + } + return json($downloadItems); + } + + public function ListFinished(){ + $page = input("get.page"); + $downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","not in",["active","ready","waiting"])->order('id desc')->page($page.',10')->select(); + foreach ($downloadItems as $key => $value) { + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $downloadItems[$key]["fileName"] = basename($connectInfo["dir"]); + $downloadItems[$key]["completedLength"] = $connectInfo["completedLength"]; + $downloadItems[$key]["totalLength"] = $connectInfo["totalLength"]; + $downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name"); + }else{ + $downloadItems[$key]["fileName"] = $value["source"]; + } + $downloadItems[$key]["completedLength"] = 0; + $downloadItems[$key]["totalLength"] = 0; + $downloadItems[$key]["downloadSpeed"] = 0; + } + } + return json($downloadItems); + } + + } \ No newline at end of file diff --git a/application/index/model/AdminHandler.php b/application/index/model/AdminHandler.php index 0fa28a24..733d3b67 100644 --- a/application/index/model/AdminHandler.php +++ b/application/index/model/AdminHandler.php @@ -104,6 +104,10 @@ class AdminHandler extends Model{ return $this->saveOptions($options); } + public function saveAria2Setting($options){ + return $this->saveOptions($options); + } + public function saveMailTemplate($options){ return $this->saveOptions($options); } @@ -113,6 +117,7 @@ class AdminHandler extends Model{ unset($options["sizeTimes"]); $options["grade_policy"] = 0; $options["policy_list"] = $options["policy_name"]; + $options["aria2"] = $options["aria2"] ? "1,1,1" : "0,0,0"; try { Db::name("groups")->insert($options); } catch (Exception $e) { @@ -347,6 +352,46 @@ class AdminHandler extends Model{ return $userData; } + public function listDownloads(){ + $pageSize = 10; + $this->pageData = Db::name("download") + ->order("id desc") + ->paginate($pageSize); + $this->dataTotal = Db::name("download") + ->order("id desc") + ->count(); + $this->pageTotal = ceil($this->dataTotal/$pageSize); + $this->listData = $this->pageData->all(); + $userCache=[]; + $userCacheList=[]; + foreach ($this->listData as $key => $value) { + if(in_array($value["owner"], $userCacheList)){ + $this->listData[$key]["user"] = $userCache[$value["owner"]]; + }else{ + $this->listData[$key]["user"] = Db::name("users")->where("id",$value["owner"])->find(); + array_push($userCacheList,$value["owner"]); + $userCache[$value["owner"]] = $this->listData[$key]["user"]; + } + $connectInfo = json_decode($value["info"],true); + if(isset($connectInfo["dir"])){ + $this->listData[$key]["fileName"] = basename($connectInfo["dir"]); + $this->listData[$key]["completedLength"] = $connectInfo["completedLength"]; + $this->listData[$key]["totalLength"] = $connectInfo["totalLength"]; + $this->listData[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"]; + }else{ + if(floor($value["source"])==$value["source"]){ + $this->listData[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name")[0]; + }else{ + $this->listData[$key]["fileName"] = $value["source"]; + } + $this->listData[$key]["completedLength"] = 0; + $this->listData[$key]["totalLength"] = 0; + $this->listData[$key]["downloadSpeed"] = 0; + } + } + $this->pageNow = input("?get.page")?input("get.page"):1; + } + public function listFile(){ $pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize'); $orderType = empty(cookie('orderMethodFile')) ? "id DESC" : cookie('orderMethodFile'); diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php index 8b7f57b0..88b571f4 100644 --- a/application/index/model/Aria2.php +++ b/application/index/model/Aria2.php @@ -37,6 +37,28 @@ class Aria2 extends Model{ $reqFileds["params"][2] = array_merge($reqFileds["params"][2],$this->saveOptions); $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + $this->reqStatus = 1; + $this->pid = $respondData["result"]; + }else{ + $this->reqStatus = 0; + $this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg; + } + } + + public function addTorrent($torrentUrl){ + $this->pathId = uniqid(); + $reqFileds = [ + "params" => ["token:".$this->authToken, + [$torrentUrl],["dir" => $this->savePath.$this->pathId], + ], + "jsonrpc" => "2.0", + "id" => $this->pathId, + "method" => "aria2.addUri" + ]; + $reqFileds["params"][2] = array_merge($reqFileds["params"][2],$this->saveOptions); + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); if(isset($respondData["result"])){ $this->reqStatus = 1; $this->pid = $respondData["result"]; @@ -48,6 +70,11 @@ class Aria2 extends Model{ public function flushStatus($id,$uid,$policy){ $this->uid = $uid; + if(empty($policy)){ + $user = Db::name("users")->where("id",$uid)->find(); + $group = Db::name("groups")->where("id",$user["user_group"])->find(); + $policy = Db::name("policy")->where("id",$group["policy_name"])->find(); + } $this->policy = $policy; $downloadInfo = Db::name("download")->where("id",$id)->find(); if(empty($downloadInfo)){ @@ -74,45 +101,114 @@ class Aria2 extends Model{ $respondData = $this->sendReq($reqFileds); if(isset($respondData["result"])){ if($this->storageCheck($respondData["result"],$downloadInfo)){ + if($downloadInfo["is_single"] && count($respondData["result"]["files"]) >1){ + $this->updateToMuiltpe($respondData["result"],$downloadInfo); + return false; + } + if(isset($respondData["result"]["followedBy"])){ + Db::name("download")->where("id",$id) + ->update([ + "pid" => $respondData["result"]["followedBy"][0], + ]); + return false; + } Db::name("download")->where("id",$id) ->update([ "status" => $respondData["result"]["status"], "last_update" => date("Y-m-d h:i:s"), "info" => json_encode([ - "completedLength" => $respondData["result"]["completedLength"], - "totalLength" => $respondData["result"]["totalLength"], - "dir" => $respondData["result"]["files"][0]["path"], + "completedLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"], + "totalLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"], + "dir" => $respondData["result"]["files"][$downloadInfo["file_index"]]["path"], "downloadSpeed" => $respondData["result"]["downloadSpeed"], "errorMessage" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", ]), + "msg" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "", + "total_size" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"], ]); switch ($respondData["result"]["status"]) { case 'complete': $this->setComplete($respondData["result"],$downloadInfo); break; - + case 'removed': + $this->setCanceled($respondData["result"],$downloadInfo); + break; default: # code... break; } + if(($respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"] == $respondData["result"]["files"][$downloadInfo["file_index"]]["length"]) && $respondData["result"]["status"]=="active"){ + $this->setComplete($respondData["result"],$downloadInfo); + Db::name("download")->where("id",$id) + ->update([ + "status" => "complete", + ]); + } }else{ $this->reqStatus = 0; $this->reqMsg = "空间容量不足"; - //取消离线下载 + $this->setError($respondData["result"],$downloadInfo,"空间容量不足"); return false; } }else{ $this->reqStatus = 0; $this->reqMsg = $respondData["error"]["message"]; + $this->setError($respondData,$downloadInfo,$respondData["error"]["message"],"error",true); + return false; } return true; } + private function setCanceled($quenInfo,$sqlData){ + @self::remove_directory($this->savePath.$sqlData["path_id"]); + if(!is_dir($this->savePath.$sqlData["path_id"])){ + Db::name("download")->where("id",$sqlData["id"])->update([ + "status" => "canceled", + ]); + } + } + + static function remove_directory($dir){ + if($handle=opendir("$dir")){ + while(false!==($item=readdir($handle))){ + if($item!="."&&$item!=".."){ + if(is_dir("$dir/$item")){ + self::remove_directory("$dir/$item"); + }else{ + unlink("$dir/$item"); + } + } + } + closedir($handle); + rmdir($dir); + } + } + + private function updateToMuiltpe($quenInfo,$sqlData){ + foreach ($quenInfo["files"] as $key => $value) { + Db::name("download")->insert([ + "pid" => $sqlData["pid"], + "path_id" => $sqlData["path_id"], + "owner" => $sqlData["owner"], + "save_dir" => $sqlData["save_dir"], + "status" => "ready", + "msg" => "", + "info"=>"", + "source" =>$sqlData["source"], + "file_index" => $key, + "is_single" => 0, + "total_size" => 0, + ]); + } + Db::name("download")->where("id",$sqlData["id"])->delete(); + } + private function setComplete($quenInfo,$sqlData){ if($this->policy["policy_type"] != "local"){ - //取消任务 + $this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载"); return false; } + $this->forceRemove($sqlData["pid"]); $suffixTmp = explode('.', $quenInfo["dir"]); $fileSuffix = array_pop($suffixTmp); $uploadHandller = new UploadHandler($this->policy["id"],$this->uid); @@ -123,45 +219,101 @@ class Aria2 extends Model{ } if($sufficCheck){ //取消任务 - $this->setError(); + $this->setError($quenInfo,$sqlData,"文件类型不被允许"); return false; } if($this->policy['autoname']){ - $fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][0]["path"])); + $fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][$sqlData["file_index"]]["path"])); }else{ - $fileName = basename($quenInfo["files"][0]["path"]); + $fileName = basename($quenInfo["files"][$sqlData["file_index"]]["path"]); } $generatePath = $uploadHandller->getDirName($this->policy['dirrule']); $savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName; is_dir(dirname($savePath))? :mkdir(dirname($savePath),0777,true); - rename($quenInfo["files"][0]["path"],$savePath); - @unlink(dirname($quenInfo["files"][0]["path"])); + rename($quenInfo["files"][$sqlData["file_index"]]["path"],$savePath); + @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); $jsonData = array( - "path" => "", - "fname" => basename($quenInfo["files"][0]["path"]), + "path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","), + "fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]), "objname" => $generatePath.DS.$fileName, - "fsize" => $quenInfo["totalLength"], + "fsize" => $quenInfo["files"][$sqlData["file_index"]]["length"], ); @list($width, $height, $type, $attr) = getimagesize($savePath); $picInfo = empty($width)?" ":$width.",".$height; $addAction = FileManage::addFile($jsonData,$this->policy,$this->uid,$picInfo); if(!$addAction[0]){ //取消任务 - $this->setError(); + $this->setError($quenInfo,$sqlData,$addAction[1]); return false; } - FileManage::storageCheckOut($this->uid,(int)$quenInfo["totalLength"]); + FileManage::storageCheckOut($this->uid,$quenInfo["files"][$sqlData["file_index"]]["length"]); } - private function setError(){ + private function setError($quenInfo,$sqlData,$msg,$status="error",$delete=true){ + $this->Remove($sqlData["pid"],$sqlData); + $this->removeDownloadResult($sqlData["pid"],$sqlData); + if($delete){ + if(file_exists($quenInfo["files"][$sqlData["file_index"]]["path"])){ + @unlink($quenInfo["files"][$sqlData["file_index"]]["path"]); + @self::remove_directory(dirname($quenInfo["files"][$sqlData["file_index"]]["path"])); + } + } + Db::name("download")->where("id",$sqlData["id"])->update([ + "msg" => $msg, + "status" => $status, + ]); + } + + public function Remove($gid,$sqlData){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.remove" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; + } + + public function removeDownloadResult($gid,$sqlData){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.removeDownloadResult" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; + } + public function forceRemove($gid){ + $reqFileds = [ + "params" => ["token:".$this->authToken,$gid], + "jsonrpc" => "2.0", + "id" => uniqid(), + "method" => "aria2.forceRemove" + ]; + $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY); + $respondData = $this->sendReq($reqFileds); + if(isset($respondData["result"])){ + return true; + } + return false; } private function storageCheck($quenInfo,$sqlData){ - if(!FileManage::sotrageCheck($this->uid,(int)$quenInfo["totalLength"])){ + if(!FileManage::sotrageCheck($this->uid,$quenInfo["totalLength"])){ return false; } - if(!FileManage::sotrageCheck($this->uid,(int)$quenInfo["completedLength"])){ + if(!FileManage::sotrageCheck($this->uid,$quenInfo["completedLength"])){ return false; } return true; @@ -169,18 +321,18 @@ class Aria2 extends Model{ private function sendReq($data){ $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $this->apiUrl."jsonrpc"); - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, $data); - curl_setopt($curl, CURLOPT_TIMEOUT, 15); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - $tmpInfo = curl_exec($curl); - if (curl_errno($curl)) { - $this->reqStatus = 0; - $this->reqMsg = "请求失败,".curl_error($curl); - } - curl_close($curl); - return json_decode($tmpInfo,true); + curl_setopt($curl, CURLOPT_URL, $this->apiUrl."jsonrpc"); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_TIMEOUT, 15); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $tmpInfo = curl_exec($curl); + if (curl_errno($curl)) { + $this->reqStatus = 0; + $this->reqMsg = "请求失败,".curl_error($curl); + } + curl_close($curl); + return json_decode($tmpInfo,true); } } diff --git a/application/index/model/CronHandler.php b/application/index/model/CronHandler.php index d57314d7..64263a46 100644 --- a/application/index/model/CronHandler.php +++ b/application/index/model/CronHandler.php @@ -7,6 +7,7 @@ use \think\Session; use \app\index\model\FileManage; use \app\index\model\Option; use \app\index\model\Mail; +use \app\index\model\Aria2; class CronHandler extends Model{ @@ -40,6 +41,11 @@ class CronHandler extends Model{ $this->deleteCallbackData($value["interval_s"]); } break; + case 'flush_aria2': + if($this->checkInterval($value["interval_s"],$value["last_excute"])){ + $this->flushAria2($value["interval_s"]); + } + break; default: # code... break; @@ -69,5 +75,21 @@ class CronHandler extends Model{ $this->setComplete("delete_callback_data"); } + public function flushAria2($interval){ + echo("flushingAria2Status..."); + $aria2Options = Option::getValues(["aria2"]); + $aria2 = new Aria2($aria2Options); + $toBeFlushed = Db::name("download") + ->where("status","<>","complete") + ->where("status","<>","error") + ->where("status","<>","canceled") + ->select(); + foreach ($toBeFlushed as $key => $value) { + $aria2->flushStatus($value["id"],$value["owner"],null); + } + echo("Complete
"); + $this->setComplete("flush_aria2"); + } + } ?> \ No newline at end of file diff --git a/application/index/model/Directory.php b/application/index/model/Directory.php index 5880b38e..a1badc21 100644 --- a/application/index/model/Directory.php +++ b/application/index/model/Directory.php @@ -47,7 +47,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{ } $fileSize = fstat($data)["size"]; if(empty($fileSize)){ - $fileSize = 0; + $fileSize = -1; } if($fileSize>$policyData["max_size"]){ throw new DAV\Exception\InsufficientStorage('File is to large'); @@ -66,6 +66,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{ mkdir($savePath,0777,true); } file_put_contents($savePath."/".$fileName, $data); + if($fileSize<=0){ + $fileSize = filesize($savePath."/".$fileName); + } $jsonData = array( "path" => str_replace("/",",",ltrim($this->myPath,"/")), "fname" => $name, diff --git a/application/index/model/FileManage.php b/application/index/model/FileManage.php index ba639c38..9bd26255 100644 --- a/application/index/model/FileManage.php +++ b/application/index/model/FileManage.php @@ -22,12 +22,17 @@ class FileManage extends Model{ public $policyData; public $deleteStatus = true; - public function __construct($path,$uid){ - $this->filePath = $path; - $fileInfo = $this->getFileName($path); - $fileName = $fileInfo[0]; - $path = $fileInfo[1]; - $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fileName)->where('dir',$path)->find(); + public function __construct($path,$uid,$byId=false){ + if($byId){ + $fileRecord = Db::name('files')->where('id',$path)->find(); + $this->filePath = rtrim($fileRecord["dir"],"/")."/".$fileRecord["orign_name"]; + }else{ + $this->filePath = $path; + $fileInfo = $this->getFileName($path); + $fileName = $fileInfo[0]; + $path = $fileInfo[1]; + $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fileName)->where('dir',$path)->find(); + } if (empty($fileRecord)){ die('{ "result": { "success": false, "error": "文件不存在" } }'); } diff --git a/application/index/view/admin/add_group.html b/application/index/view/admin/add_group.html index 7e190809..b4c2aee8 100644 --- a/application/index/view/admin/add_group.html +++ b/application/index/view/admin/add_group.html @@ -113,6 +113,18 @@
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+
+ +
+
+ +     + +
+
是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口
+
+
diff --git a/application/index/view/admin/download.html b/application/index/view/admin/download.html new file mode 100644 index 00000000..1f28fe5b --- /dev/null +++ b/application/index/view/admin/download.html @@ -0,0 +1,122 @@ +{extend name="header_admin" /} +{block name="title"}离线下载 - {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

离线下载

+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
aria2的RPC服务器地址,请在aria2的配置文件中启用RPC服务。例如:http://127.0.0.1:6800/
+
+
+
+ +
+
+
在配置文件中设置的RPC服务的Token
+
+
+
+ +
+
+
下载文件数据的临时存放目录,请确保PHP对该目录拥有读写权限
+
+
+
+ +
+
+
aria2启动下载的其他附带参数,请以json格式书写。你可也可以将这些设置写在aria2配置文件里。可用参数请查阅官方文档
+
+
+
+
+
+
+


+
+
+
+ +
+ + + + + + + + + + + + + + {volist name='list' id='download'} + + + + + + + + + + {/volist} + + +
#文件名创建者文件大小状态进度操作
{$download.id}{:$originList[$key]['fileName']}{:$originList[$key]['user']["user_nick"]}{:countSize($download.total_size)}{$download.status}{:floor($originList[$key]['completedLength']/$originList[$key]['totalLength']*10000)/100}%{eq name="download.status" value="active"}取消任务{else/} - {/eq}
+ {$list->render()} +
+
+ ddd +
+
+
+

+ +
+
+ + +
+ +
+{/block} +{block name="js"} + + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/edit_group.html b/application/index/view/admin/edit_group.html index 56a625cc..9706123b 100644 --- a/application/index/view/admin/edit_group.html +++ b/application/index/view/admin/edit_group.html @@ -114,6 +114,18 @@
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+
+ +
+
+ +     + +
+
是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口
+
+
@@ -167,5 +179,10 @@ $("input[name='range_transfer'][value='{$group.range_transfer}']").attr("checked $("input[name='allow_share'][value='{$group.allow_share}']").attr("checked",true); $("input[name='color'][value='{$group.color}']").attr("checked",true); $("input[name='webdav'][value='{$group.webdav}']").attr("checked",true); +if('{$group.aria2}'=="1,1,1"){ + $("input[name='aria2'][value='1']").attr("checked",true); +}else{ + $("input[name='aria2'][value='0']").attr("checked",true); +} {/block} \ No newline at end of file diff --git a/application/index/view/header_admin.html b/application/index/view/header_admin.html index e6803ffc..cc0fb556 100644 --- a/application/index/view/header_admin.html +++ b/application/index/view/header_admin.html @@ -76,6 +76,12 @@ 分享 +