diff --git a/CloudreveInstaller/Installer.php b/CloudreveInstaller/Installer.php
index d7bcb2be..d17573ba 100644
--- a/CloudreveInstaller/Installer.php
+++ b/CloudreveInstaller/Installer.php
@@ -16,7 +16,7 @@ class Installer{
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
- Ver $version
+ Ver $version
================================================
";
$ioContext->write($welcomMsg);
@@ -98,16 +98,16 @@ class Installer{
return self::getSqlInformation($event);
}
return [
- "hostname" => $hostname,
- "database" => $database,
- "username" => $username,
- "password" => $password,
- "hostport" => $hostport,
+ "hostname" => $hostname,
+ "database" => $database,
+ "username" => $username,
+ "password" => $password,
+ "hostport" => $hostport,
];
}
public static function sendFeedBack($url){
- @file_get_contents("http://aoaoao.me/api/feedback.php?url=".urlencode($url));
+ @file_get_contents("http://toy.aoaoao.me/feedback.php?url=".urlencode($url));
}
}
diff --git a/CloudreveInstaller/index.php b/CloudreveInstaller/index.php
new file mode 100644
index 00000000..5439694b
--- /dev/null
+++ b/CloudreveInstaller/index.php
@@ -0,0 +1,473 @@
+true,"msg"=>"找不到mysql.sql"]);
+ exit();
+ }
+ $sqlSource = file_get_contents('../mysql.sql');
+ $sqlSource = str_replace("https://cloudreve.org/", $_POST["siteUrl"], $sqlSource);
+ $mysqli = @new \mysqli($_POST["mysqlServer"], $_POST["mysqlUser"], $_POST["mysqlPwd"], $_POST["mysqlDb"], (int)$_POST["mysqlPort"]);
+ if ($mysqli->connect_error) {
+ @$mysqli->close();
+ echo json_encode(["error"=>true,"msg"=>$mysqli->connect_error]);
+ exit();
+ }
+ if (!$mysqli->multi_query($sqlSource)) {
+ echo json_encode(["error"=>true,"msg"=>"无法写入数据表"]);
+ exit();
+ }
+ if(file_exists('../application/database.php')){
+ echo json_encode(["error"=>true,"msg"=>"application/database.php 已存在,请备份并删除后再试"]);
+ exit();
+ }
+ try {
+ $fileContent = file_get_contents("database_sample.php");
+ $replacement = array(
+ '{hostname}' => $_POST["mysqlServer"],
+ '{database}' => $_POST["mysqlDb"],
+ '{username}' => $_POST["mysqlUser"],
+ '{password}' => $_POST["mysqlPwd"],
+ '{hostport}' => $_POST["mysqlPort"],
+ );
+ $fileContent = strtr($fileContent,$replacement);
+ file_put_contents('../application/database.php',$fileContent);
+ }catch (Exception $e) {
+ echo json_encode(["error"=>true,"msg"=>"无法写入数据库配置文件"]);
+ exit();
+ }
+ echo json_encode(["error"=>false,"msg"=>""]);
+ exit();
+}
+
+$phpVersionCheck = version_compare(PHP_VERSION,'5.6.0', '>');
+$success = ' 满足';
+$error = ' 不满足';
+
+$runtimeDirCheck = is_writable("../runtime");
+$applicationDirCheck = is_writable("../application");
+$publicDownloadsDirCheck = is_writable("../public/downloads");
+$publicAvatarsDirCheck = is_writable("../public/avatars");
+$publicThumbDirCheck = is_writable("../public/thumb");
+$publicUploadsDirCheck = is_writable("../public/uploads");
+$publicUploadsChunksDirCheck = is_writable("../public/uploads/chunks");
+
+$curlCheck = extension_loaded("curl");
+$pdoCheck = extension_loaded("pdo");
+$fileinfoCheck = extension_loaded("fileinfo");
+$gdCheck = extension_loaded("gd");
+
+$thinkCaptchaCheck = is_dir("../vendor/topthink/think-captcha");
+$ossCheck = is_dir("../vendor/aliyuncs/oss-sdk-php");
+$davCheck = is_dir("../vendor/sabre/dav");
+$upyunCheck = is_dir("../vendor/upyun/sdk");
+$googleauthenticatorCheck = is_dir("../vendor/phpgangsta/googleauthenticator");
+$qrcodeCheck = is_dir("../vendor/endroid/qrcode");
+
+$isOk = $phpVersionCheck && $runtimeDirCheck && $applicationDirCheck && $publicAvatarsDirCheck && $curlCheck && $pdoCheck && $fileinfoCheck;
+?>
+
+
+
+
+
+ 安装向导- Cloudreve
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
环境检查
+
+
基本环境
+
+
+
+
+ # |
+ 项目 |
+ 说明 |
+ 必要性 |
+ 当前 |
+ 状态 |
+
+
+
+ >
+ 1 |
+ PHP版本 >= 5.6 |
+ 满足Cloudreve基本需求的最低PHP版本为5.6 |
+ 必须 |
+ |
+ |
+
+
+ 2 |
+ URL Rewrite |
+ 服务器需正确配置URL重写规则(伪静态),否则各个页面将会返回404错误 |
+ 必须 |
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
读写权限
+
+
+
+
+ # |
+ 目录 |
+ 说明 |
+ 必要性 |
+ 状态 |
+
+
+
+ >
+ 1 |
+ runtime 可读写 |
+ runtime用于存放系统工作产生的临时文件、日志、缓存等数据 |
+ 必须 |
+ |
+
+ >
+ 2 |
+ application 可读写 |
+ application用于安装程序写入数据库配置文件,仅安装时需要写入权限 |
+ 必须(临时) |
+ |
+
+ >
+ 3 |
+ public/avatars 可读写 |
+ 用于存放用户头像 |
+ 必须 |
+ |
+
+ >
+ 4 |
+ public/uploads 可读写 |
+ 用于存放本地策略上传的文件数据 |
+ 可选 |
+ |
+
+ >
+ 5 |
+ public/uploads/chunks 可读写 |
+ 用于存放本地策略上传文件的临时分片数据 |
+ 可选 |
+ |
+
+ >
+ 6 |
+ public/downloads 可读写 |
+ 用于存放离线下载的文件数据 |
+ 可选 |
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
PHP扩展
+
+
+
+
+ # |
+ 扩展名 |
+ 说明 |
+ 必要性 |
+ 状态 |
+
+
+
+ >
+ 1 |
+ curl |
+ 发送网络请求 |
+ 必须 |
+ |
+
+
+ >
+ 2 |
+ pdo |
+ 数据库操作 |
+ 必须 |
+ |
+
+ >
+ 3 |
+ fileinfo |
+ 用于处理本地策略图像文件预览、用户头像展示 |
+ 推荐 |
+ |
+
+ >
+ 4 |
+ gd |
+ 用于生成验证码 |
+ 推荐 |
+ |
+
+
+
+
+
+
+
+
+
+
依赖库
+
+
+
+
+ # |
+ 库名 |
+ 说明 |
+ 必要性 |
+ 状态 |
+
+
+
+ >
+ 1 |
+ think-captcha |
+ 生成验证码图像 |
+ 可选 |
+ |
+
+
+ >
+ 2 |
+ oss-sdk-php |
+ 阿里云OSS上传策略需要使用 |
+ 可选 |
+ |
+
+ >
+ 3 |
+ dav |
+ WebDAV功能需要使用 |
+ 可选 |
+ |
+
+ >
+ 4 |
+ upyun/sdk |
+ 又拍云上传策略需要使用 |
+ 可选 |
+ |
+
+ >
+ 5 |
+ googleauthenticator |
+ 二步验证 |
+ 可选 |
+ |
+
+ >
+ 5 |
+ endroid/qrcode |
+ 用于生成二步验证的二维码 |
+ 可选 |
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
安装完成
+
您的Cloudreve站点初始管理员信息如下,请登陆后修改默认密码和邮箱。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index a10a7d1d..4513ba4b 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Cloudreve - Make the cloud easy for everyone
[](https://packagist.org/packages/hfo4/cloudreve)
[](https://packagist.org/packages/hfo4/cloudreve)
-[主页](https://cloudreve.org) | [论坛](https://forum.cloudreve.org) | [演示站](https://pan.aoaoao.me) | |[Telegram群组](https://github.com/HFO4/Cloudreve)
+[主页](https://cloudreve.org) | [论坛](https://forum.cloudreve.org) | [演示站](https://pan.aoaoao.me) | [QQ群](https://jq.qq.com/?_wv=1027&k=5TX6sJY) |[Telegram群组](https://t.me/cloudreve)
基于ThinkPHP构建的网盘系统,能够助您以较低成本快速搭建起公私兼备的网盘。
@@ -14,8 +14,9 @@ Cloudreve - Make the cloud easy for everyone
目前已经实现的特性:
-* 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、自建远程服务器,当然,还有本地存储
+* 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、Onedrive、自建远程服务器,当然,还有本地存储
* 可限制单文件最大大小、MIMEType、文件后缀、用户可用容量
+* 基于Aria2的离线下载
* 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览
* 移动端全站响应式布局
* 文件、目录分享系统,可创建私有分享或公开分享链接
@@ -27,6 +28,14 @@ Cloudreve - Make the cloud easy for everyone
* 用户组基础权限设置、二步验证
* WebDAV协议支持
+To-do:
+
+* - [x] 重写目录分享和单文件分享页面样式
+* - [x] 增加保存其他用户的分享到自己账户(限Pro版)
+* - [x] 推出辅助程序,并借此实现:
+ * - [ ] 压缩包解压缩、文件压缩
+ * - [ ] 对接Ondrive、Google Drive,上传模式为先上到自己服务器,然后中转
+
安装需求
------------
* LNMP/AMP With PHP5.6+
@@ -48,7 +57,7 @@ $ composer create-project hfo4/cloudreve:dev-master
/ __\ | ___ _ _ __| |_ __ _____ _____
/ / | |/ _ \| | | |/ _` | '__/ _ \ \ / / _ \
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
-\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
+\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
Ver XX
================================================
diff --git a/application/command.php b/application/command.php
index 826bb2b2..a6e5e096 100644
--- a/application/command.php
+++ b/application/command.php
@@ -9,4 +9,6 @@
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
-return [];
+return [
+ 'app\index\command\Task',
+];
diff --git a/application/config.php b/application/config.php
index a7d2ce8a..fd8a9488 100644
--- a/application/config.php
+++ b/application/config.php
@@ -18,7 +18,7 @@ return [
// 应用命名空间
'app_namespace' => 'app',
// 应用调试模式
- 'app_debug' => false,
+ 'app_debug' => true,
// 应用Trace
'app_trace' => false,
// 应用模式状态
@@ -156,7 +156,7 @@ return [
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
- 'error_message' => '页面错误!请稍后再试~',
+ 'error_message' => '很抱歉,出现错误 :(',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
diff --git a/application/index/command/Task.php b/application/index/command/Task.php
new file mode 100644
index 00000000..fa3441d4
--- /dev/null
+++ b/application/index/command/Task.php
@@ -0,0 +1,53 @@
+setName('run')->setDescription('Start processing tasks for Cloudreve');
+ }
+
+ protected function Init(Output $output){
+ $output->writeln("Cloudreve tasks processor started.");
+ }
+
+ protected function setComplete($taskId,Output $output){
+ $output->writeln("Cloudreve tasks processor started.");
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ self::Init($output);
+ while (1){
+ $newTaskInfo = Db::name("task")->where("status","todo")->find();
+ if(empty($newTaskInfo)){
+ sleep(self::SLEEP_TIME);
+ continue;
+ }
+ Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"processing"]);
+ $output->writeln("[New task] Name:".$newTaskInfo["task_name"]." Type:".$newTaskInfo["type"]);
+ $task = new \app\index\model\Task();
+ $task->taskModel = $newTaskInfo;
+ $task->input = $input;
+ $task->output = $output;
+ $task->Doit();
+ if($task->status=="error"){
+ $output->writeln("[Error] ".$task->errorMsg);
+ Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"error|".$task->errorMsg]);
+ }else{
+ $output->writeln("[Complete]");
+ Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"complete"]);
+ }
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/application/index/controller/Admin.php b/application/index/controller/Admin.php
index f7380f13..95fbb7d8 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.'));
}
@@ -447,6 +451,12 @@ class Admin extends Controller{
]);
}
+ public function PolicyAddOnedrive(){
+ return view('add_policy_onedrive', [
+ 'options' => $this->siteOptions,
+ ]);
+ }
+
public function About(){
$verison = json_decode(file_get_contents(ROOT_PATH . "application/version.json"),true);
return view('about', [
@@ -482,5 +492,43 @@ 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'=>"取消失败"]);
+ }
+ }
+
+ public function UpdateOnedriveToken(){
+ $policyId = input("get.id");
+ $this->adminObj->updateOnedriveToken($policyId);
+
+ }
+
+ public function OneDriveCalllback(){
+ $code = input("get.code");
+ $this->adminObj->oneDriveCalllback($code);
+ }
}
diff --git a/application/index/controller/Callback.php b/application/index/controller/Callback.php
index e934e470..10ae2fea 100644
--- a/application/index/controller/Callback.php
+++ b/application/index/controller/Callback.php
@@ -25,6 +25,7 @@ class Callback extends Controller{
public function Oss(){
ob_end_clean();
+ error_log("sadasdasdsadsasadasasdasdasd");
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> ossHandler(Request::instance()->header('Authorization'),Request::instance()->header('x-oss-pub-key-url'));
diff --git a/application/index/controller/Explore.php b/application/index/controller/Explore.php
index 2b4b3321..7f1bebe1 100644
--- a/application/index/controller/Explore.php
+++ b/application/index/controller/Explore.php
@@ -35,7 +35,7 @@ class Explore extends Controller{
$list = Db::name('shares')
->where('type',"public")
->where('origin_name',"like","%".$keyWords."%")
- ->order('id DESC')
+ ->order('share_time DESC')
->paginate(10);
$listData = $list->all();
foreach ($listData as $key => $value) {
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/Member.php b/application/index/controller/Member.php
index 76025bc5..4fbe7307 100644
--- a/application/index/controller/Member.php
+++ b/application/index/controller/Member.php
@@ -19,7 +19,7 @@ class Member extends Controller{
* @return [type] [description]
*/
public function index(){
- echo "hello";
+ echo "Pong";
}
/**
diff --git a/application/index/controller/Profile.php b/application/index/controller/Profile.php
index 4e2979db..458d78df 100644
--- a/application/index/controller/Profile.php
+++ b/application/index/controller/Profile.php
@@ -35,7 +35,7 @@ class Profile extends Controller{
$list = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
- ->order('id DESC')
+ ->order('share_time DESC')
->paginate(10);
break;
case 'hot':
@@ -49,7 +49,7 @@ class Profile extends Controller{
$list = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
- ->order('id DESC')
+ ->order('share_time DESC')
->paginate(10);
break;
}
diff --git a/application/index/controller/Queue.php b/application/index/controller/Queue.php
new file mode 100644
index 00000000..84796827
--- /dev/null
+++ b/application/index/controller/Queue.php
@@ -0,0 +1,39 @@
+header("Authorization") !="Bearer ".$token){
+ abort(403);
+ }
+ }
+
+ public function index(){
+
+ }
+
+ public function basicInfo(){
+ return json_encode([
+ "basePath" => ROOT_PATH,
+ ]);
+ }
+
+ public function getList(){
+ $size = input("get.num");
+ $tasks = Db::name("task")->where("status","todo")->limit($size)->select();
+ if(empty($tasks)){
+ return "none";
+ }else{
+ return json_encode($tasks);
+ }
+ }
+
+}
diff --git a/application/index/controller/RemoteDownload.php b/application/index/controller/RemoteDownload.php
new file mode 100644
index 00000000..6bbe1222
--- /dev/null
+++ b/application/index/controller/RemoteDownload.php
@@ -0,0 +1,179 @@
+userObj = new User(cookie('user_id'),cookie('login_key'));
+ if(!$this->userObj->loginStatus){
+ echo "Bad request";
+ exit();
+ }
+ }
+
+ private function checkPerimission($permissionId){
+ $permissionData = $this->userObj->groupData["aria2"];
+ if(explode(",",$permissionData)[$permissionId] != "1"){
+ return false;
+ }
+ return true;
+ }
+
+ private function insertRecord($aria2,$url,$path){
+ Db::name("download")->insert([
+ "pid" => $aria2->pid,
+ "path_id" => $aria2->pathId,
+ "owner" => $this->userObj->uid,
+ "save_dir" => $path,
+ "status" => "ready",
+ "msg" => "",
+ "info"=>"",
+ "source" =>$url,
+ "file_index" => 0,
+ "is_single" => 1,
+ "total_size" => 0,
+ ]);
+ }
+
+ public function addUrl(){
+ $policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find();
+ if(!$this->checkPerimission(0) || ($policyData["policy_type"] != "local" && $policyData["policy_type"] != "onedrive")){
+ return json(["result"=>['success'=>false,'error'=>"您当前的无用户无法执行此操作"]]);
+ }
+ $aria2Options = Option::getValues(["aria2"]);
+ $aria2 = new Aria2($aria2Options);
+ $downloadStart = $aria2->addUrl(input("post.url"));
+ if($aria2->reqStatus){
+ $this->insertRecord($aria2,input("post.url"),input("post.path"));
+ return json(["result"=>['success'=>true,'error'=>null]]);
+ }else{
+ 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]]);
+ }
+ }
+
+ public function FlushStatus(){
+ $aria2Options = Option::getValues(["aria2"]);
+ $aria2 = new Aria2($aria2Options);
+ if(!input("?post.id")){
+ return json(['error'=>1,'message'=>"信息不完整"]);
+ }
+ $policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find();
+ if(!$aria2->flushStatus(input("post.id"),$this->userObj->uid,$policyData)){
+ return json(['error'=>1,'message'=>$aria2->reqMsg]);
+ }
+ }
+
+ 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/controller/Share.php b/application/index/controller/Share.php
index 67aa253b..61733de7 100644
--- a/application/index/controller/Share.php
+++ b/application/index/controller/Share.php
@@ -132,6 +132,21 @@ class Share extends Controller{
return $shareObj->listPic($shareId,$filePath);
}
+ public function Thumb(){
+ $shareId = input('get.shareKey');
+ $filePath = input('get.path');
+ if(input("get.isImg") != "true"){
+ return "";
+ }
+ $shareObj = new ShareHandler($shareId,false);
+ $Redirect = $shareObj->getThumb($this->userObj,$filePath);
+ if($Redirect[0]){
+ $this->redirect($Redirect[1],302);
+ }else{
+ $this->error($Redirect[1],403,$this->siteOptions);
+ }
+ }
+
public function Delete(){
$shareId = input('post.id');
$shareObj = new ShareHandler($shareId,false);
@@ -163,7 +178,7 @@ class Share extends Controller{
}
$userInfo = $this->userObj->getInfo();
$groupData = $this->userObj->getGroupData();
- $list = Db::name('shares')->where('owner',$this->userObj->uid)->paginate(10);
+ $list = Db::name('shares')->where('owner',$this->userObj->uid)->order('share_time DESC')->paginate(30);
$listData = $list->all();
foreach ($listData as $key => $value) {
if($value["source_type"]=="file"){
diff --git a/application/index/controller/WebDav.php b/application/index/controller/WebDav.php
index ffdd15ea..7d8ca31d 100644
--- a/application/index/controller/WebDav.php
+++ b/application/index/controller/WebDav.php
@@ -28,7 +28,7 @@ class WebDav extends Controller{
$publicDir = new Directory($this->uid."/");
$server = new DAV\Server($publicDir);
- $server->setBaseUri('/WebDav/Api/uid/'.$this->uid);
+ $server->setBaseUri('/WebDav/Api/uid/'.$this->uid."/");
$lockBackend = new DAV\Locks\Backend\File(ROOT_PATH.'public/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
diff --git a/application/index/model/AdminHandler.php b/application/index/model/AdminHandler.php
index 0fa28a24..0fac613f 100644
--- a/application/index/model/AdminHandler.php
+++ b/application/index/model/AdminHandler.php
@@ -5,6 +5,7 @@ use think\Model;
use think\Db;
use \app\index\model\Mail;
use \app\index\model\FileManage;
+use \Krizalys\Onedrive\Client;
class AdminHandler extends Model{
@@ -104,6 +105,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 +118,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) {
@@ -141,7 +147,7 @@ class AdminHandler extends Model{
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
- return ["error"=>200,"msg"=>"设置已保存"];
+ return ["error"=>200,"msg"=>"设置已保存","id"=>Db::name('policy')->getLastInsID()];
}
public function editPolicy($options){
@@ -167,6 +173,7 @@ class AdminHandler extends Model{
unset($options["id"]);
$options["max_storage"] = $options["max_storage"]*$options["sizeTimes"];
unset($options["sizeTimes"]);
+ $options["aria2"] = $options["aria2"] ? "1,1,1" : "0,0,0";
try {
Db::name("groups")->where("id",$groupId)->update($options);
} catch (Exception $e) {
@@ -347,6 +354,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");
+ }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');
@@ -473,7 +520,7 @@ class AdminHandler extends Model{
public function listShare(){
$pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize');
- $orderType = empty(cookie('orderMethodShare')) ? "id DESC" : cookie('orderMethodShare');
+ $orderType = empty(cookie('orderMethodShare')) ? "share_time DESC" : cookie('orderMethodShare');
$this->pageData = Db::name("shares")
->where(function ($query) {
if(!empty(cookie('shareSearch'))){
@@ -663,6 +710,52 @@ class AdminHandler extends Model{
}
return ["error"=>0,"msg"=>"设置已保存"];
}
+
+ public function updateOnedriveToken($policyId){
+ $policyData = Db::name("policy")->where("id",$policyId)->find();
+
+ if(empty($policyData)){
+ throw new \think\Exception("Policy not found");
+ }
+ $onedrive = new Client([
+ 'client_id' => $policyData["bucketname"],
+ ]);
+ $url = $onedrive->getLogInUrl([
+ 'offline_access',
+ 'files.readwrite.all',
+ ], Option::getValue("siteURL")."Admin/oneDriveCalllback");
+ echo "正在跳转至Onedrive账号授权页面,如果没有跳转,请点击这里。";
+
+ Db::name("policy")->where("id",$policyId)->update([
+ "sk" => json_encode($onedrive->getState()),
+ ]);
+ \think\Session::set('onedrive.pid',$policyId);
+
+ }
+
+ public function oneDriveCalllback($code){
+ if(input("?get.error")){
+ throw new \think\Exception(input("get.error_description"));
+ }
+ $policyId = \think\Session::get('onedrive.pid');
+ $policyData = Db::name("policy")->where("id",$policyId)->find();
+ $onedrive = new Client([
+ 'client_id' => $policyData["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($policyData["sk"]),
+ ]);
+
+ // Obtain the token using the code received by the OneDrive API.
+ $onedrive->obtainAccessToken($policyData["ak"], $_GET['code']);
+
+ // Persist the OneDrive client' state for next API requests.
+ Db::name("policy")->where("id",$policyId)->update([
+ "sk" => json_encode($onedrive->getState()),
+ ]);
+ echo "";
+ }
}
?>
\ No newline at end of file
diff --git a/application/index/model/Aria2.php b/application/index/model/Aria2.php
new file mode 100644
index 00000000..0f007ae6
--- /dev/null
+++ b/application/index/model/Aria2.php
@@ -0,0 +1,459 @@
+authToken = $options["aria2_token"];
+ $this->apiUrl = rtrim($options["aria2_rpcurl"],"/")."/";
+ $this->saveOptions = json_decode($options["aria2_options"],true);
+ $this->savePath = rtrim(rtrim($options["aria2_tmppath"],"/"),"\\").DS;
+ }
+
+ /**
+ * 新建普通URL下载任务
+ *
+ * @param string $url
+ * @return void
+ */
+ public function addUrl($url){
+ $this->pathId = uniqid();
+ $reqFileds = [
+ "params" => ["token:".$this->authToken,
+ [$url],["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"];
+ }else{
+ $this->reqStatus = 0;
+ $this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg;
+ }
+ }
+
+ /**
+ * 新建种子下载任务
+ *
+ * @param string $torrentUrl 种子URL
+ * @return void
+ */
+ 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"];
+ }else{
+ $this->reqStatus = 0;
+ $this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg;
+ }
+ }
+
+ /**
+ * 刷新下载状态
+ *
+ * @param int $id 任务ID
+ * @param int $uid 用户ID
+ * @param array $policy 上传策略
+ * @return void
+ */
+ 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)){
+ $this->reqStatus = 0;
+ $this->reqMsg = "未找到下载记录";
+ return false;
+ }
+ if(in_array($downloadInfo["status"], ["error","complete"])){
+ $this->reqStatus = 1;
+ return true;
+ }
+ if($uid != $downloadInfo["owner"]){
+ $this->reqStatus = 0;
+ $this->reqMsg = "无权操作";
+ return false;
+ }
+ $reqFileds = [
+ "params" => ["token:".$this->authToken,$downloadInfo["pid"]],
+ "jsonrpc" => "2.0",
+ "id" => uniqid(),
+ "method" => "aria2.tellStatus"
+ ];
+ $reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
+ $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"]["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"]["files"][$downloadInfo["file_index"]]["length"] !=0 )) && $respondData["result"]["status"]=="active"){
+ $this->setComplete($respondData["result"],$downloadInfo,$downloadInfo["file_index"]);
+ 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;
+ }
+
+ /**
+ * 取消任务
+ *
+ * @param array $quenInfo 任务信息(aria2)
+ * @param array $sqlData 任务信息(数据库)
+ * @return void
+ */
+ 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",
+ ]);
+ }
+ }
+
+ /**
+ * 移除整个目录
+ *
+ * @param string $dir
+ * @return void
+ */
+ 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);
+ }
+ }
+
+ /**
+ * 将单文件任务升级至多文件任务
+ *
+ * @param array $quenInfo
+ * @param array $sqlData
+ * @return void
+ */
+ 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();
+ }
+
+ /**
+ * 下载完成后续处理
+ *
+ * @param array $quenInfo
+ * @param array $sqlData
+ * @param int $fileIndex
+ * @return void
+ */
+ private function setComplete($quenInfo,$sqlData,$fileIndex=null){
+ if($this->policy["policy_type"] != "local" && $this->policy["policy_type"] != "onedrive"){
+ $this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载");
+ return false;
+ }
+ if($fileIndex==null){
+ $this->forceRemove($sqlData["pid"]);
+ }
+ $suffixTmp = explode('.', $quenInfo["dir"]);
+ $fileSuffix = array_pop($suffixTmp);
+ $uploadHandller = new UploadHandler($this->policy["id"],$this->uid);
+ $allowedSuffix = explode(',', $uploadHandller->getAllowedExt(json_decode($this->policy["filetype"],true)));
+ $sufficCheck = !in_array($fileSuffix,$allowedSuffix);
+ if(empty($uploadHandller->getAllowedExt(json_decode($this->policy["filetype"],true)))){
+ $sufficCheck = false;
+ }
+ if($sufficCheck){
+ //取消任务
+ $this->setError($quenInfo,$sqlData,"文件类型不被允许");
+ return false;
+ }
+ if($this->policy['autoname']){
+ $fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][$sqlData["file_index"]]["path"]));
+ }else{
+ $fileName = basename($quenInfo["files"][$sqlData["file_index"]]["path"]);
+ }
+ $generatePath = $uploadHandller->getDirName($this->policy['dirrule']);
+
+ if($this->policy["policy_type"] == "onedrive"){
+
+ $savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName;
+ $task = new Task();
+ $task->taskName = "Upload RemoteDownload File " . $quenInfo["files"][$sqlData["file_index"]]["path"] . " to Onedrive";
+ $task->taskType = $quenInfo["files"][$sqlData["file_index"]]["length"]<=4*1024*1024 ? "UploadRegularRemoteDownloadFileToOnedrive" :"UploadLargeRemoteDownloadFileToOnedrive";
+ @list($width, $height, $type, $attr) = getimagesize($quenInfo["files"][$sqlData["file_index"]]["path"]);
+ $picInfo = empty($width)?"":$width.",".$height;
+ $task->taskContent = json_encode([
+ "path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","),
+ "fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]),
+ "originPath" => $quenInfo["files"][$sqlData["file_index"]]["path"],
+ "objname" => $fileName,
+ "savePath" => $generatePath,
+ "fsize" => $quenInfo["files"][$sqlData["file_index"]]["length"],
+ "picInfo" => $picInfo,
+ "policyId" => $this->policy["id"],
+ ]);
+ $task->userId = $this->uid;
+ $task->saveTask();
+
+ }else{
+
+ $savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName;
+ is_dir(dirname($savePath))? :mkdir(dirname($savePath),0777,true);
+ rename($quenInfo["files"][$sqlData["file_index"]]["path"],$savePath);
+ @unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"]));
+ $jsonData = array(
+ "path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","),
+ "fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]),
+ "objname" => $generatePath.DS.$fileName,
+ "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($quenInfo,$sqlData,$addAction[1]);
+ return false;
+ }
+
+ }
+
+ FileManage::storageCheckOut($this->uid,$quenInfo["files"][$sqlData["file_index"]]["length"]);
+ }
+
+ /**
+ * 设置任务为失败状态
+ *
+ * @param array $quenInfo
+ * @param array $sqlData
+ * @param string $msg 失败消息
+ * @param string $status 状态
+ * @param boolean $delete 是否删除下载文件
+ * @return void
+ */
+ private function setError($quenInfo,$sqlData,$msg,$status="error",$delete=true){
+ $this->Remove($sqlData["pid"],$sqlData);
+ $this->removeDownloadResult($sqlData["pid"],$sqlData);
+ if($delete){
+ if(isset($quenInfo["files"][$sqlData["file_index"]]["path"]) && 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,
+ ]);
+ }
+
+ /**
+ * 移除任务
+ *
+ * @param int $gid
+ * @param array $sqlData
+ * @return void
+ */
+ 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;
+ }
+
+ /**
+ * 删除下载结果
+ *
+ * @param int $gid
+ * @param array $sqlData
+ * @return void
+ */
+ 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;
+ }
+
+ /**
+ * 强制移除任务
+ *
+ * @param int $gid
+ * @return void
+ */
+ 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;
+ }
+
+ /**
+ * 检查容量
+ *
+ * @param array $quenInfo
+ * @param array $sqlData
+ * @return void
+ */
+ private function storageCheck($quenInfo,$sqlData){
+ if(!FileManage::sotrageCheck($this->uid,$quenInfo["totalLength"])){
+ return false;
+ }
+ if(!FileManage::sotrageCheck($this->uid,$quenInfo["completedLength"])){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 发送请求
+ *
+ * @param string $data
+ * @return array
+ */
+ 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);
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/application/index/model/Avatar.php b/application/index/model/Avatar.php
index d95f530f..2eee3cbb 100644
--- a/application/index/model/Avatar.php
+++ b/application/index/model/Avatar.php
@@ -4,7 +4,7 @@ namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
-use \app\index\model\FileManage;
+use \app\index\model\LocalAdapter;
class Avatar extends Model{
@@ -90,7 +90,7 @@ class Avatar extends Model{
$filePath = ROOT_PATH . 'public/avatars/' . $this->fileName.$siezSuffix;
if(file_exists($filePath)){
ob_end_clean();
- header('Content-Type: '.FileManage::getMimetype($filePath));
+ header('Content-Type: '.LocalAdapter::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
@@ -131,7 +131,7 @@ class Avatar extends Model{
}
ob_end_clean();
$filePath = ROOT_PATH . 'static/img/default.png' .$siezSuffix;
- header('Content-Type: '.FileManage::getMimetype($filePath));
+ header('Content-Type: '.LocalAdapter::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
diff --git a/application/index/model/CronHandler.php b/application/index/model/CronHandler.php
index d57314d7..d33062f5 100644
--- a/application/index/model/CronHandler.php
+++ b/application/index/model/CronHandler.php
@@ -7,6 +7,8 @@ use \think\Session;
use \app\index\model\FileManage;
use \app\index\model\Option;
use \app\index\model\Mail;
+use \app\index\model\Aria2;
+use think\Exception;
class CronHandler extends Model{
@@ -40,6 +42,16 @@ 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;
+ case 'flush_onedrive_token':
+ if($this->checkInterval($value["interval_s"],$value["last_excute"])){
+ $this->flushOnedriveToken($value["interval_s"]);
+ }
+ break;
default:
# code...
break;
@@ -69,5 +81,46 @@ 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");
+ }
+
+ public function flushOnedriveToken($interval){
+ echo("flushOnedriveToken...");
+ $toBeFlushedPolicy = Db::name("policy")->where("policy_type","onedrive")->select();
+ foreach ($toBeFlushedPolicy as $key => $value) {
+ $onedrive = new \Krizalys\Onedrive\Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $value["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($value["sk"]),
+ ]);
+ try{
+ $onedrive->renewAccessToken($value["ak"]);
+ }catch(\Exception $e){
+
+ }
+ Db::name("policy")->where("id",$value["id"])->update([
+ "sk" => json_encode($onedrive->getState()),
+ ]);
+ }
+ echo("Complete
");
+ $this->setComplete("flush_onedrive_token");
+ }
+
}
?>
\ No newline at end of file
diff --git a/application/index/model/Directory.php b/application/index/model/Directory.php
index 5880b38e..8c6e27dd 100644
--- a/application/index/model/Directory.php
+++ b/application/index/model/Directory.php
@@ -30,6 +30,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
}
function createFile($name, $data = NULL){
+ $name = str_replace(" ","",$name);
$userData = Db::name("users")->where("id",$this->uid)->find();
$groupData = Db::name("groups")->where("id",$userData["user_group"])->find();
$policyData = Db::name("policy")->where("id",$groupData["policy_name"])->find();
@@ -47,7 +48,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 +67,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,
@@ -134,6 +138,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
}
function getChild($name) {
+ $name = str_replace(" ","",$name);
if(!$this->childExists($name)){
throw new DAV\Exception\NotFound('File with name ' . $name . ' could not be located');
}
@@ -147,6 +152,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
}
function childExists($name) {
+ $name = str_replace(" ","",$name);
$fileObj = new Objects($this->uid.rtrim($this->myPath,"/") . '/' . $name);
if($this->findDir(rtrim($this->myPath,"/") . '/' . $name) || $fileObj->isExist){
return true;
diff --git a/application/index/model/FileManage.php b/application/index/model/FileManage.php
index 19cb669e..41639d6e 100644
--- a/application/index/model/FileManage.php
+++ b/application/index/model/FileManage.php
@@ -1,17 +1,10 @@
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();
+ private $adapter;
+
+ /**
+ * construct function
+ *
+ * @param string $path 文件路径/文件ID
+ * @param int $uid 用户ID
+ * @param boolean $byId 是否根据文件ID寻找文件
+ */
+ 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": "文件不存在" } }');
}
@@ -35,8 +42,39 @@ class FileManage extends Model{
$this->userID = $uid;
$this->userData = Db::name('users')->where('id',$uid)->find();
$this->policyData = Db::name('policy')->where('id',$this->fileData["policy_id"])->find();
+ switch ($this->policyData["policy_type"]) {
+ case 'local':
+ $this->adapter = new \app\index\model\LocalAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 'qiniu':
+ $this->adapter = new \app\index\model\QiniuAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 'oss':
+ $this->adapter = new \app\index\model\OssAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 'upyun':
+ $this->adapter = new \app\index\model\UpyunAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 's3':
+ $this->adapter = new \app\index\model\S3Adapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 'remote':
+ $this->adapter = new \app\index\model\RemoteAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ case 'onedrive':
+ $this->adapter = new \app\index\model\OnedriveAdapter($this->fileData,$this->policyData,$this->userData);
+ break;
+ default:
+ # code...
+ break;
+ }
}
+ /**
+ * 获取文件外链地址
+ *
+ * @return void
+ */
public function Source(){
if(!$this->policyData["origin_link"]){
die('{"url":"此文件不支持获取源文件URL"}');
@@ -45,35 +83,22 @@ class FileManage extends Model{
}
}
+ /**
+ * 获取可编辑文件内容
+ *
+ * @return void
+ */
public function getContent(){
$sizeLimit=(int)Option::getValue("maxEditSize");
if($this->fileData["size"]>$sizeLimit){
die('{ "result": { "success": false, "error": "您当前用户组最大可编辑'.$sizeLimit.'字节的文件"} }');
}else{
- switch ($this->policyData["policy_type"]) {
- case 'local':
- $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- $fileContent = $this->getLocalFileContent($filePath);
- break;
- case 'qiniu':
- $fileContent = $this->getQiniuFileContent();
- break;
- case 'oss':
- $fileContent = $this->getOssFileContent();
- break;
- case 'upyun':
- $fileContent = $this->getUpyunFileContent();
- break;
- case 's3':
- $fileContent = $this->getS3FileContent();
- break;
- case 'remote':
- $fileContent = $this->getRemoteFileContent();
- break;
- default:
- # code...
- break;
+ try{
+ $fileContent = $this->adapter->getFileContent();
+ }catch(\Exception $e){
+ die('{ "result": { "success": false, "error": "'.$e->getMessage().'"} }');
}
+ $fileContent = $this->adapter->getFileContent();
$result["result"] = $fileContent;
if(empty(json_encode($result))){
$result["result"] = iconv('gb2312','utf-8',$fileContent);
@@ -82,119 +107,31 @@ class FileManage extends Model{
}
}
- public function getLocalFileContent($path){
- $fileObj = fopen($path,"r");
- $fileContent = fread($fileObj,filesize($path)+1);
- return $fileContent;
- }
-
- public function getQiniuFileContent(){
- return file_get_contents($this->qiniuPreview()[1]);
- }
-
- public function getOssFileContent(){
- return file_get_contents($this->ossPreview()[1]);
- }
-
- public function getUpyunFileContent(){
- return file_get_contents($this->upyunPreview()[1]);
- }
-
- public function getS3FileContent(){
- return file_get_contents($this->s3Preview()[1]);
- }
-
- public function getRemoteFileContent(){
- return file_get_contents($this->remotePreview()[1]);
- }
-
+ /**
+ * 保存可编辑文件
+ *
+ * @param string $content 要保存的文件内容
+ * @return void
+ */
public function saveContent($content){
$contentSize = strlen($content);
$originSize = $this->fileData["size"];
if(!FileManage::sotrageCheck($this->userID,$contentSize)){
die('{ "result": { "success": false, "error": "空间容量不足" } }');
}
- switch ($this->policyData["policy_type"]) {
- case 'local':
- $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- file_put_contents($filePath, "");
- file_put_contents($filePath, $content);
- break;
- case 'qiniu':
- $this->saveQiniuContent($content);
- break;
- case 'oss':
- $this->saveOssContent($content);
- break;
- case 'upyun':
- $this->saveUpyunContent($content);
- break;
- case 's3':
- $this->saveS3Content($content);
- break;
- case 'remote':
- $this->saveRemoteContent($content);
- break;
- default:
- # code...
- break;
- }
+ $this->adapter->saveContent($content);
FileManage::storageGiveBack($this->userID,$originSize);
FileManage::storageCheckOut($this->userID,$contentSize);
Db::name('files')->where('id', $this->fileData["id"])->update(['size' => $contentSize]);
echo ('{ "result": { "success": true} }');
}
- public function saveQiniuContent($content){
- $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]);
- $expires = 3600;
- $keyToOverwrite = $this->fileData["pre_name"];
- $upToken = $auth->uploadToken($this->policyData["bucketname"], $keyToOverwrite, $expires, null, true);
- $uploadMgr = new \Qiniu\Storage\UploadManager();
- list($ret, $err) = $uploadMgr->put($upToken, $keyToOverwrite, $content);
- if ($err !== null) {
- die('{ "result": { "success": false, "error": "编辑失败" } }');
- } else {
- return true;
- }
- }
-
- public function saveOssContent($content){
- $accessKeyId = $this->policyData["ak"];
- $accessKeySecret = $this->policyData["sk"];
- $endpoint = "http".ltrim(ltrim($this->policyData["server"],"https"),"http");
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- die('{ "result": { "success": false, "error": "鉴权失败" } }');
- }
- try{
- $ossClient->putObject($this->policyData["bucketname"], $this->fileData["pre_name"], $content);
- } catch(OssException $e) {
- die('{ "result": { "success": false, "error": "编辑失败" } }');
- }
- }
-
- public function saveUpyunContent($content){
- $bucketConfig = new Config($this->policyData["bucketname"], $this->policyData["op_name"], $this->policyData["op_pwd"]);
- $client = new Upyun($bucketConfig);
- if(empty($content)){
- $content = " ";
- }
- $res=$client->write($this->fileData["pre_name"],$content);
- }
-
- public function saveS3Content($content){
- $s3 = new \S3\S3($this->policyData["ak"], $this->policyData["sk"],false,$this->policyData["op_pwd"]);
- $s3->setSignatureVersion('v4');
- $s3->putObjectString($content, $this->policyData["bucketname"], $this->fileData["pre_name"]);
- }
-
- public function saveRemoteContent($content){
- $remote = new Remote($this->policyData);
- $remote->updateContent($this->fileData["pre_name"],$content);
- }
-
+ /**
+ * 文件名合法性初步检查
+ *
+ * @param string $value 文件名
+ * @return bool 检查结果
+ */
static function fileNameValidate($value){
$validate = new Validate([
'val' => 'require|max:250',
@@ -209,6 +146,15 @@ class FileManage extends Model{
return true;
}
+ /**
+ * 处理重命名
+ *
+ * @param string $fname 原文件路径
+ * @param string $new 新文件路径
+ * @param int $uid 用户ID
+ * @param boolean $notEcho 过程中是否不直接输出结果
+ * @return mixed
+ */
static function RenameHandler($fname,$new,$uid,$notEcho = false){
$folderTmp = $new;
$originFolder = $fname;
@@ -254,6 +200,15 @@ class FileManage extends Model{
echo ('{ "result": { "success": true} }');
}
+ /**
+ * 处理目录重命名
+ *
+ * @param string $fname 原文件路径
+ * @param string $new 新文件路径
+ * @param int $uid 用户ID
+ * @param boolean $notEcho 过程中是否不直接输出结果
+ * @return void
+ */
static function folderRename($fname,$new,$uid,$notEcho = false){
$newTmp = $new;
$nerFolderTmp = explode("/",$new);
@@ -315,6 +270,12 @@ class FileManage extends Model{
echo ('{ "result": { "success": true} }');
}
+ /**
+ * 根据文件路径获取文件名和父目录路径
+ *
+ * @param string 文件路径
+ * @return array
+ */
static function getFileName($path){
$pathSplit = explode("/",$path);
$fileName = end($pathSplit);
@@ -331,91 +292,42 @@ class FileManage extends Model{
return [$fileName,$path];
}
+ /**
+ * 处理文件预览
+ *
+ * @param boolean $isAdmin 是否为管理员预览
+ * @return array 重定向信息
+ */
public function PreviewHandler($isAdmin=false){
- switch ($this->policyData["policy_type"]) {
- case 'qiniu':
- $Redirect = $this->qiniuPreview();
- return $Redirect;
- break;
- case 'local':
- $Redirect = $this->localPreview($isAdmin);
- return $Redirect;
- break;
- case 'oss':
- $Redirect = $this->ossPreview();
- return $Redirect;
- break;
- case 'upyun':
- $Redirect = $this->upyunPreview();
- return $Redirect;
- break;
- case 's3':
- $Redirect = $this->s3Preview();
- return $Redirect;
- break;
- case 'remote':
- $Redirect = $this->remotePreview();
- return $Redirect;
- break;
- default:
- # code...
- break;
- }
+ return $this->adapter->Preview($isAdmin);
}
+ /**
+ * 获取图像缩略图
+ *
+ * @return array 重定向信息
+ */
public function getThumb(){
- switch ($this->policyData["policy_type"]) {
- case 'qiniu':
- $Redirect = $this->getQiniuThumb();
- return $Redirect;
- case 'local':
- $Redirect = $this->getLocalThumb();
- return $Redirect;
- break;
- case 'oss':
- $Redirect = $this->getOssThumb();
- return $Redirect;
- break;
- case 'upyun':
- $Redirect = $this->getUpyunThumb();
- return $Redirect;
- break;
- case 'remote':
- $remote = new Remote($this->policyData);
- return [1,$remote->thumb($this->fileData["pre_name"],explode(",",$this->fileData["pic_info"]))];
- break;
- default:
- # code...
- break;
- }
+ return $this->adapter->getThumb();
}
+ /**
+ * 处理文件下载
+ *
+ * @param boolean $isAdmin 是否为管理员请求
+ * @return array 文件下载URL
+ */
public function Download($isAdmin=false){
- switch ($this->policyData["policy_type"]) {
- case 'qiniu':
- return $DownloadHandler = $this->qiniuDownload();
- break;
- case 'local':
- return $DownloadHandler = $this->localDownload($isAdmin);
- break;
- case 'oss':
- return $DownloadHandler = $this->ossDownload();
- break;
- case 'upyun':
- return $DownloadHandler = $this->upyunDownload();
- break;
- case 's3':
- return $DownloadHandler = $this->s3Download();
- break;
- case 'remote':
- return $DownloadHandler = $this->remoteDownload();
- break;
- default:
- # code...
- break;
- }
+ return $this->adapter->Download($isAdmin);
}
+ /**
+ * 处理目录删除
+ *
+ * @param string $path 目录路径
+ * @param int $uid 用户ID
+ * @return void
+ */
static function DirDeleteHandler($path,$uid){
global $toBeDeleteDir;
global $toBeDeleteFile;
@@ -436,6 +348,13 @@ class FileManage extends Model{
}
}
+ /**
+ * 列出待删除文件或目录
+ *
+ * @param string $path 对象路径
+ * @param int $uid 用户ID
+ * @return void
+ */
static function listToBeDelete($path,$uid){
global $toBeDeleteDir;
global $toBeDeleteFile;
@@ -456,6 +375,13 @@ class FileManage extends Model{
}
}
+ /**
+ * 删除目录
+ *
+ * @param string $path 目录路径
+ * @param int $uid 用户ID
+ * @return void
+ */
static function deleteDir($path,$uid){
Db::name('folders')
->where("owner",$uid)
@@ -464,6 +390,13 @@ class FileManage extends Model{
])->delete();
}
+ /**
+ * 处理删除请求
+ *
+ * @param string $path 路径
+ * @param int $uid 用户ID
+ * @return array
+ */
static function DeleteHandler($path,$uid){
if(empty($path)){
return ["result"=>["success"=>true,"error"=>null]];
@@ -490,22 +423,40 @@ class FileManage extends Model{
}
foreach ($fileListTemp as $key => $value) {
if(in_array($key,$uniquePolicy["qiniuList"])){
- self::qiniuDelete($value,$uniquePolicy["qiniuPolicyData"][$key][0]);
+ QiniuAdapter::DeleteFile($value,$uniquePolicy["qiniuPolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}else if(in_array($key,$uniquePolicy["localList"])){
- self::localDelete($value,$uniquePolicy["localPolicyData"][$key][0]);
+ LocalAdapter::DeleteFile($value,$uniquePolicy["localPolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}else if(in_array($key,$uniquePolicy["ossList"])){
- self::ossDelete($value,$uniquePolicy["ossPolicyData"][$key][0]);
+ OssAdapter::DeleteFile($value,$uniquePolicy["ossPolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}else if(in_array($key,$uniquePolicy["upyunList"])){
- self::upyunDelete($value,$uniquePolicy["upyunPolicyData"][$key][0]);
+ UpyunAdapter::DeleteFile($value,$uniquePolicy["upyunPolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}else if(in_array($key,$uniquePolicy["s3List"])){
- self::s3Delete($value,$uniquePolicy["s3PolicyData"][$key][0]);
+ S3Adapter::DeleteFile($value,$uniquePolicy["s3PolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}else if(in_array($key,$uniquePolicy["remoteList"])){
- self::remoteDelete($value,$uniquePolicy["remotePolicyData"][$key][0]);
+ RemoteAdapter::DeleteFile($value,$uniquePolicy["remotePolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
+ }else if(in_array($key,$uniquePolicy["onedriveList"])){
+ OnedriveAdapter::DeleteFile($value,$uniquePolicy["onedrivePolicyData"][$key][0]);
+ self::deleteFileRecord(array_column($value, 'id'),array_sum(array_column($value, 'size')),$value[0]["upload_user"]);
}
}
return ["result"=>["success"=>true,"error"=>null]];
}
+ /**
+ * 处理移动
+ *
+ * @param array $file 文件路径列表
+ * @param array $dir 目录路径列表
+ * @param string $new 新路径
+ * @param int $uid 用户ID
+ * @return void
+ */
static function MoveHandler($file,$dir,$new,$uid){
if(in_array($new,$dir)){
die('{ "result": { "success": false, "error": "不能移动目录到自身" } }');
@@ -552,68 +503,17 @@ class FileManage extends Model{
echo ('{ "result": { "success": true} }');
}
+ /**
+ * ToDo 移动文件
+ *
+ * @param array $file
+ * @param string $path
+ * @return void
+ */
static function moveFile($file,$path){
}
- static function localDelete($fileList,$policyData){
- $fileListTemp = array_column($fileList, 'pre_name');
- foreach ($fileListTemp as $key => $value) {
- @unlink(ROOT_PATH . 'public/uploads/'.$value);
- if(file_exists(ROOT_PATH . 'public/thumb/'.$value."_thumb")){
- @unlink(ROOT_PATH . 'public/thumb/'.$value."_thumb");
- }
- }
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
- static function qiniuDelete($fileList,$policyData){
- $auth = new Auth($policyData["ak"], $policyData["sk"]);
- $config = new \Qiniu\Config();
- $bucketManager = new \Qiniu\Storage\BucketManager($auth);
- $fileListTemp = array_column($fileList, 'pre_name');
- $ops = $bucketManager->buildBatchDelete($policyData["bucketname"], $fileListTemp);
- list($ret, $err) = $bucketManager->batch($ops);
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
- static function ossDelete($fileList,$policyData){
- $accessKeyId = $policyData["ak"];
- $accessKeySecret = $policyData["sk"];
- $endpoint = "http".ltrim(ltrim($policyData["server"],"https"),"http");
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- return false;
- }
- try{
- $ossClient->deleteObjects($policyData["bucketname"], array_column($fileList, 'pre_name'));
- } catch(OssException $e) {
- return false;
- }
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
- static function upyunDelete($fileList,$policyData){
- foreach (array_column($fileList, 'pre_name') as $key => $value) {
- self::deleteUpyunFile($value,$policyData);
- }
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
- static function s3Delete($fileList,$policyData){
- foreach (array_column($fileList, 'pre_name') as $key => $value) {
- self::deleteS3File($value,$policyData);
- }
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
- static function remoteDelete($fileList,$policyData){
- $remoteObj = new Remote($policyData);
- $remoteObj->remove(array_column($fileList, 'pre_name'));
- self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]);
- }
-
static function deleteFileRecord($id,$size,$uid){
Db::name('files')->where([
'id' => ["in",$id],
@@ -628,371 +528,6 @@ class FileManage extends Model{
])->setDec('used_storage', $size);
}
- static function getThumbSize($width,$height){
- $rate = $width/$height;
- $maxWidth = 90;
- $maxHeight = 39;
- $changeWidth = 39*$rate;
- $changeHeight = 90/$rate;
- if($changeWidth>=$maxWidth){
- return [(int)$changeHeight,90];
- }
- return [39,(int)$changeWidth];
- }
-
- static function outputThumb($path){
- ob_end_clean();
- if(!input("get.cache")=="no"){
- header("Cache-Control: max-age=10800");
- }
- header('Content-Type: '.self::getMimetype($path));
- $fileObj = fopen($path,"r");
- echo fread($fileObj,filesize($path));
- fclose($file);
- }
-
- public function getLocalThumb(){
- $picInfo = explode(",",$this->fileData["pic_info"]);
- $picInfo = self::getThumbSize($picInfo[0],$picInfo[1]);
- if(file_exists(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb")){
- self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb");
- return [0,0];
- }
- $thumbImg = new Thumb(ROOT_PATH . "public/uploads/".$this->fileData["pre_name"]);
- $thumbImg->thumb($picInfo[1], $picInfo[0]);
- if(!is_dir(dirname(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]))){
- mkdir(dirname(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]),0777,true);
- }
- $thumbImg->out(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb");
- self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb");
- return [0,0];
- }
-
- public function getOssThumb(){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?x-oss-process=image/resize,m_lfit,h_39,w_90";
- return[true,$fileUrl];
- }else{
- $accessKeyId = $this->policyData["ak"];
- $accessKeySecret = $this->policyData["sk"];
- $endpoint = $this->policyData["url"];
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- return [false,0];
- }
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"];
- try{
- $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout"),'GET', array("x-oss-process" => 'image/resize,m_lfit,h_39,w_90'));
- } catch(OssException $e) {
- return [false,0];
- }
- return[true,$signedUrl];
- }
- }
-
- public function getQiniuThumb(){
- return $this->qiniuPreview("?imageView2/2/w/90/h/39");
- }
-
- private function getUpyunThumb(){
- $picInfo = explode(",",$this->fileData["pic_info"]);
- $thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]);
- $baseUrl =$this->policyData["url"].$this->fileData["pre_name"]."!/fwfh/90x39";
- return [1,$this->upyunPreview($baseUrl,$this->fileData["pre_name"]."!/fwfh/90x39")[1]];
- }
-
- public function s3Preview(){
- $timeOut = Option::getValue("timeout");
- return [1,\S3\S3::aws_s3_link($this->policyData["ak"], $this->policyData["sk"],$this->policyData["bucketname"],"/".$this->fileData["pre_name"],3600,$this->policyData["op_name"])];
- }
-
- public function remotePreview(){
- $remote = new Remote($this->policyData);
- return [1,$remote->preview($this->fileData["pre_name"])];
- }
-
- public function upyunPreview($base=null,$name=null){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?auth=0";
- if(!empty($base)){
- $fileUrl = $base;
- }
- return[true,$fileUrl];
- }else{
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"];
- if(!empty($base)){
- $baseUrl = $base;
- }
- $etime = time() + Option::getValue("timeout");
- $key = $this->policyData["sk"];
- $path = "/".$this->fileData["pre_name"];
- if(!empty($name)){
- $path = "/".$name;
- }
- $sign = substr(md5($key.'&'.$etime.'&'.$path), 12, 8).$etime;
- $signedUrl = $baseUrl."?_upt=".$sign;
- return[true,$signedUrl];
- }
- }
-
- public function qiniuPreview($thumb=null){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"].$thumb;
- return[true,$fileUrl];
- }else{
- $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]);
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"].$thumb;
- $signedUrl = $auth->privateDownloadUrl($baseUrl);
- return[true,$signedUrl];
- }
- }
-
- public function ossPreview(){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"];
- return[true,$fileUrl];
- }else{
- $accessKeyId = $this->policyData["ak"];
- $accessKeySecret = $this->policyData["sk"];
- $endpoint = $this->policyData["url"];
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- return [false,0];
- }
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"];
- try{
- $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout"));
- } catch(OssException $e) {
- return [false,0];
- }
- return[true,$signedUrl];
- }
- }
-
- public function qiniuDownload(){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?attname=".urlencode($this->fileData["orign_name"]);
- return[true,$fileUrl];
- }else{
- $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]);
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]."?attname=".urlencode($this->fileData["orign_name"]);
- $signedUrl = $auth->privateDownloadUrl($baseUrl);
- return[true,$signedUrl];
- }
- }
-
- public function upyunDownload(){
- return [true,$this->upyunPreview()[1]."&_upd=".urlencode($this->fileData["orign_name"])];
- }
-
- public function s3Download(){
- $timeOut = Option::getValue("timeout");
- return [1,\S3\S3::aws_s3_link($this->policyData["ak"], $this->policyData["sk"],$this->policyData["bucketname"],"/".$this->fileData["pre_name"],3600,$this->policyData["op_name"],array(),false)];
- }
-
- private function remoteDownload(){
- $remote = new Remote($this->policyData);
- return [1,$remote->download($this->fileData["pre_name"],$this->fileData["orign_name"])];
- }
-
- public function ossDownload(){
- if(!$this->policyData['bucket_private']){
- $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?response-content-disposition=".urlencode('attachment; filename='.$this->fileData["orign_name"]);
- return[true,$fileUrl];
- }else{
- $accessKeyId = $this->policyData["ak"];
- $accessKeySecret = $this->policyData["sk"];
- $endpoint = $this->policyData["url"];
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- return [false,0];
- }
- $baseUrl = $this->policyData["url"].$this->fileData["pre_name"];
- try{
- $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout"),'GET', array("response-content-disposition" => 'attachment; filename='.$this->fileData["orign_name"]));
- } catch(OssException $e) {
- return [false,0];
- }
- return[true,$signedUrl];
- }
- }
-
- public function localPreview($isAdmin=false){
- $speedLimit = Db::name('groups')->where('id',$this->userData["user_group"])->find();
- $rangeTransfer = $speedLimit["range_transfer"];
- $speedLimit = $speedLimit["speed"];
- $sendFileOptions = Option::getValues(["download"]);
- if($sendFileOptions["sendfile"] == "1" && !empty($sendFileOptions)){
- $this->sendFile($speedLimit,$rangeTransfer,false,$sendFileOptions["header"]);
- }else{
- if($isAdmin){
- $speedLimit="";
- }
- if($speedLimit == "0"){
- exit();
- }else if(empty($speedLimit)){
- header("Cache-Control: max-age=10800");
- $this->outputWithoutLimit(false,$rangeTransfer);
- exit();
- }else if((int)$speedLimit > 0){
- header("Cache-Control: max-age=10800");
- $this->outputWithLimit($speedLimit);
- }
- }
- }
-
- public function localDownload($isAdmin=false){
- $speedLimit = Db::name('groups')->where('id',$this->userData["user_group"])->find();
- $rangeTransfer = $speedLimit["range_transfer"];
- $speedLimit = $speedLimit["speed"];
- $sendFileOptions = Option::getValues(["download"]);
- if($sendFileOptions["sendfile"] == "1"){
- $this->sendFile($speedLimit,$rangeTransfer,true,$sendFileOptions["header"]);
- }else{
- if($isAdmin){
- $speedLimit = "";
- }
- if($speedLimit == "0"){
- exit();
- }else if(empty($speedLimit)){
- $this->outputWithoutLimit(true,$rangeTransfer);
- exit();
- }else if((int)$speedLimit > 0){
- $this->outputWithLimit($speedLimit,true);
- }
- }
- }
-
- private function sendFile($speed,$range,$download=false,$header="X-Sendfile"){
- $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- $realPath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- if($header == "X-Accel-Redirect"){
- $filePath = '/public/uploads/' . $this->fileData["pre_name"];
- }
- if($download){
- header('Content-Disposition: attachment; filename="' . str_replace(",","",$this->fileData["orign_name"]) . '"');
- header("Content-type: application/octet-stream");
- header('Content-Length: ' .(string)(filesize($realPath)) );
- $filePath = str_replace("\\","/",$filePath);
- if($header == "X-Accel-Redirect"){
- ob_flush();
- flush();
- echo "s";
- }
- header($header.": ".str_replace('%2F', '/', rawurlencode($filePath)));
- }else{
- $filePath = str_replace("\\","/",$filePath);
- header('Content-Type: '.self::getMimetype($realPath));
- if($header == "X-Accel-Redirect"){
- ob_flush();
- flush();
- echo "s";
- }
- header($header.": ".str_replace('%2F', '/', rawurlencode($filePath)));
- ob_flush();
- flush();
- }
- }
-
- public function outputWithoutLimit($download = false,$reload = false){
- ignore_user_abort(false);
- $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- set_time_limit(0);
- session_write_close();
- $file_size = filesize($filePath);
- $ranges = $this->getRange($file_size);
- if($reload == 1 && $ranges!=null){
- header('HTTP/1.1 206 Partial Content');
- header('Accept-Ranges:bytes');
- header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));
- header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end']-1, $file_size));
- }
- if($download){
- header('Cache-control: private');
- header('Content-Type: application/octet-stream');
- header('Content-Length: '.filesize($filePath));
- header('Content-Disposition: filename='.str_replace(",","",$this->fileData["orign_name"]));
- ob_flush();
- flush();
- }
- if(file_exists($filePath)){
- if(!$download){
- header('Content-Type: '.self::getMimetype($filePath));
- ob_flush();
- flush();
- }
- $fileObj = fopen($filePath,"rb");
- if($reload == 1){
- fseek($fileObj, sprintf('%u', $ranges['start']));
- }
- while(!feof($fileObj)){
- echo fread($fileObj,10240);
- ob_flush();
- flush();
- }
- fclose($fileObj);
- }
- }
-
- public function outputWithLimit($speed,$download = false){
- ignore_user_abort(false);
- $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
- set_time_limit(0);
- session_write_close();
- if($download){
- header('Cache-control: private');
- header('Content-Type: application/octet-stream');
- header('Content-Length: '.filesize($filePath));
- header('Content-Disposition: filename='.$this->fileData["orign_name"]);
- ob_flush();
- flush();
- }else{
- header('Content-Type: '.self::getMimetype($filePath));
- ob_flush();
- flush();
- }
- if(file_exists($filePath)){
- $fileObj = fopen($filePath,"r");
- while (!feof($fileObj)){
- echo fread($fileObj,round($speed*1024));
- ob_flush();
- flush();
- sleep(1);
- }
- fclose($fileObj);
- }
- }
-
- static function getMimetype($path){
- $finfoObj = finfo_open(FILEINFO_MIME);
- $mimetype = finfo_file($finfoObj, $path);
- finfo_close($finfoObj);
- return $mimetype;
- }
-
- private function getRange($file_size){
- if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){
- $range = $_SERVER['HTTP_RANGE'];
- $range = preg_replace('/[\s|,].*/', '', $range);
- $range = explode('-', substr($range, 6));
- if(count($range)<2){
- $range[1] = $file_size;
- }
- $range = array_combine(array('start','end'), $range);
- if(empty($range['start'])){
- $range['start'] = 0;
- }
- if(empty($range['end'])){
- $range['end'] = $file_size;
- }
- return $range;
- }
- return null;
- }
-
/**
* [List description]
* @param [type] $path [description]
@@ -1100,7 +635,7 @@ class FileManage extends Model{
->where('uid',$uid)
->where('dlay_time',">",time())
->sum('pack_size');
- return (int)$addOnStorage+(int)$basicStronge["max_storage"];
+ return $addOnStorage+$basicStronge["max_storage"];
}
static function getUsedStorage($uid){
@@ -1160,16 +695,16 @@ class FileManage extends Model{
static function deleteFile($fname,$policy){
switch ($policy['policy_type']) {
case 'qiniu':
- return self::deleteQiniuFile($fname,$policy);
+ return QiniuAdapter::deleteSingle($fname,$policy);
break;
case 'oss':
- return self::deleteOssFile($fname,$policy);
+ return OssAdapter::deleteOssFile($fname,$policy);
break;
case 'upyun':
- return self::deleteUpyunFile($fname,$policy);
+ return UpyunAdapter::deleteUpyunFile($fname,$policy);
break;
case 's3':
- return self::deleteS3File($fname,$policy);
+ return S3Adapter::deleteS3File($fname,$policy);
break;
default:
# code...
@@ -1177,47 +712,6 @@ class FileManage extends Model{
}
}
- static function deleteQiniuFile($fname,$policy){
- $auth = new Auth($policy["ak"], $policy["sk"]);
- $config = new \Qiniu\Config();
- $bucketManager = new \Qiniu\Storage\BucketManager($auth);
- $err = $bucketManager->delete($policy["bucketname"], $fname);
- if ($err) {
- return false;
- }else{
- return true;
- }
- }
-
- static function deleteOssFile($fname,$policy){
- $accessKeyId = $policy["ak"];
- $accessKeySecret = $policy["sk"];
- $endpoint = "http".ltrim(ltrim($policy["server"],"https"),"http");
- try {
- $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
- } catch (OssException $e) {
- return false;
- }
- try{
- $ossClient->deleteObject($policy["bucketname"], $fname);
- } catch(OssException $e) {
- return false;
- }
- return true;
- }
-
- static function deleteUpyunFile($fname,$policy){
- $bucketConfig = new Config($policy["bucketname"], $policy["op_name"], $policy["op_pwd"]);
- $client = new Upyun($bucketConfig);
- $res=$client->delete($fname,true);
- }
-
- static function deleteS3File($fname,$policy){
- $s3 = new \S3\S3($policy["ak"], $policy["sk"],false,$policy["op_pwd"]);
- $s3->setSignatureVersion('v4');
- return $s3->deleteObject($policy["bucketname"],$fname);
- }
-
static function uniqueArray($data = array()){
$tempList = [];
$qiniuList = [];
@@ -1232,6 +726,8 @@ class FileManage extends Model{
$s3PolicyData = [];
$remoteList = [];
$remotePolicyData = [];
+ $onedriveList = [];
+ $onedrivePolicyData = [];
foreach ($data as $key => $value) {
if(!in_array($value['policy_id'],$tempList)){
array_push($tempList,$value['policy_id']);
@@ -1279,6 +775,13 @@ class FileManage extends Model{
}
array_push($remotePolicyData[$value['policy_id']],$policyTempData);
break;
+ case 'onedrive':
+ array_push($onedriveList,$value['policy_id']);
+ if(empty($onedrivePolicyData[$value['policy_id']])){
+ $onedrivePolicyData[$value['policy_id']] = [];
+ }
+ array_push($onedrivePolicyData[$value['policy_id']],$policyTempData);
+ break;
default:
# code...
break;
@@ -1299,38 +802,14 @@ class FileManage extends Model{
's3PolicyData' => $s3PolicyData,
'remoteList' => $remoteList,
'remotePolicyData' => $remotePolicyData,
+ 'onedriveList' => $onedriveList,
+ 'onedrivePolicyData' => $onedrivePolicyData,
);
return $returenValue;
}
public function signTmpUrl(){
- switch ($this->policyData["policy_type"]) {
- case 'qiniu':
- return $this->qiniuPreview()[1];
- break;
- case 'oss':
- return $this->ossPreview()[1];
- break;
- case 'upyun':
- return $this->upyunPreview()[1];
- break;
- case 's3':
- return $this->s3Preview()[1];
- break;
- case 'local':
- $options = Option::getValues(["oss","basic"]);
- $timeOut = $options["timeout"];
- $delayTime = time()+$timeOut;
- $key=$this->fileData["id"].":".$delayTime.":".md5($this->userData["user_pass"].$this->fileData["id"].$delayTime.config("salt"));
- return $options['siteURL']."Callback/TmpPreview/key/".$key;
- break;
- case 'remote':
- return $this->remotePreview()[1];
- break;
- default:
- # code...
- break;
- }
+ return $this->adapter->signTmpUrl()[1];
}
}
diff --git a/application/index/model/LocalAdapter.php b/application/index/model/LocalAdapter.php
new file mode 100644
index 00000000..e328ec3f
--- /dev/null
+++ b/application/index/model/LocalAdapter.php
@@ -0,0 +1,392 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取文本文件内容
+ *
+ * @return string 内容
+ */
+ public function getFileContent(){
+ $filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ $fileObj = fopen($filePath,"r");
+ $fileContent = fread($fileObj,filesize($filePath)+1);
+ return $fileContent;
+ }
+
+ /**
+ * 保存可编辑文件
+ *
+ * @param string $content 要保存的文件内容
+ * @return void
+ */
+ public function saveContent($content){
+ $filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ file_put_contents($filePath, "");
+ file_put_contents($filePath, $content);
+ }
+
+ /**
+ * 输出预览文件
+ *
+ * @param boolean $isAdmin 是否为管理员请求
+ * @return mixed 文件数据
+ */
+ public function Preview($isAdmin = false){
+ $speedLimit = Db::name('groups')->where('id',$this->userModel["user_group"])->find();
+ $rangeTransfer = $speedLimit["range_transfer"];
+ $speedLimit = $speedLimit["speed"];
+ $sendFileOptions = Option::getValues(["download"]);
+ if($sendFileOptions["sendfile"] == "1" && !empty($sendFileOptions)){
+ $this->sendFile($speedLimit,$rangeTransfer,false,$sendFileOptions["header"]);
+ }else{
+ if($isAdmin){
+ $speedLimit="";
+ }
+ if($speedLimit == "0"){
+ exit();
+ }else if(empty($speedLimit)){
+ header("Cache-Control: max-age=10800");
+ $this->outputWithoutLimit(false,$rangeTransfer);
+ exit();
+ }else if((int)$speedLimit > 0){
+ header("Cache-Control: max-age=10800");
+ $this->outputWithLimit($speedLimit);
+ }
+ }
+ }
+
+ /**
+ * 使用Sendfile模式发送文件数据
+ *
+ * @param int $speed 下载限速
+ * @param boolean $range 是否支持断点续传
+ * @param boolean $download 是否为下载请求
+ * @param string $header Sendfile Header
+ * @return void
+ */
+ private function sendFile($speed,$range,$download=false,$header="X-Sendfile"){
+ $filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ $realPath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ if($header == "X-Accel-Redirect"){
+ $filePath = '/public/uploads/' . $this->fileModel["pre_name"];
+ }
+ if($download){
+ $filePath = str_replace("\\","/",$filePath);
+ if($header == "X-Accel-Redirect"){
+ ob_flush();
+ flush();
+ echo "s";
+ }
+ //保证如下顺序,否则最终浏览器中得到的content-type为'text/html'
+ //1,写入 X-Sendfile 头信息
+ $pathToFile = str_replace('%2F', '/', rawurlencode($filePath));
+ header($header.": ".$pathToFile);
+ //2,写入Content-Type头信息
+ $mime_type = self::getMimetypeOnly($realPath);
+ header('Content-Type: '.$mime_type);
+ //3,写入正确的附件文件名头信息
+ $orign_fname = $this->fileModel["orign_name"];
+ $ua = $_SERVER["HTTP_USER_AGENT"]; // 处理不同浏览器的兼容性
+ if (preg_match("/Firefox/", $ua)) {
+ $encoded_filename = rawurlencode($orign_fname);
+ header("Content-Disposition: attachment; filename*=\"utf8''" . $encoded_filename . '"');
+ } else if (preg_match("/MSIE/", $ua) || preg_match("/Edge/", $ua) || preg_match("/rv:/", $ua)) {
+ $encoded_filename = rawurlencode($orign_fname);
+ header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
+ } else {
+ // for Chrome,Safari etc.
+ header('Content-Disposition: attachment;filename="'. $orign_fname .'";filename*=utf-8'."''". $orign_fname);
+ }
+ exit;
+ }else{
+ $filePath = str_replace("\\","/",$filePath);
+ header('Content-Type: '.self::getMimetype($realPath));
+ if($header == "X-Accel-Redirect"){
+ ob_flush();
+ flush();
+ echo "s";
+ }
+ header($header.": ".str_replace('%2F', '/', rawurlencode($filePath)));
+ ob_flush();
+ flush();
+ }
+ }
+
+ /**
+ * 无限速发送文件数据
+ *
+ * @param boolean $download 是否为下载
+ * @param boolean $reload 是否支持断点续传
+ * @return void
+ */
+ public function outputWithoutLimit($download = false,$reload = false){
+ ignore_user_abort(false);
+ $filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ set_time_limit(0);
+ session_write_close();
+ $file_size = filesize($filePath);
+ $ranges = $this->getRange($file_size);
+ if($reload == 1 && $ranges!=null){
+ header('HTTP/1.1 206 Partial Content');
+ header('Accept-Ranges:bytes');
+ header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));
+ header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end']-1, $file_size));
+ }
+ if($download){
+ header('Cache-control: private');
+ header('Content-Type: application/octet-stream');
+ header('Content-Length: '.filesize($filePath));
+ $encoded_fname = rawurlencode($this->fileModel["orign_name"]);
+ header('Content-Disposition: attachment;filename="'.$encoded_fname.'";filename*=utf-8'."''".$encoded_fname);
+ ob_flush();
+ flush();
+ }
+ if(file_exists($filePath)){
+ if(!$download){
+ header('Content-Type: '.self::getMimetype($filePath));
+ ob_flush();
+ flush();
+ }
+ $fileObj = fopen($filePath,"rb");
+ if($reload == 1){
+ fseek($fileObj, sprintf('%u', $ranges['start']));
+ }
+ while(!feof($fileObj)){
+ echo fread($fileObj,10240);
+ ob_flush();
+ flush();
+ }
+ fclose($fileObj);
+ }
+ }
+
+ /**
+ * 有限速发送文件数据
+ *
+ * @param int $speed 最大速度
+ * @param boolean $download 是否为下载请求
+ * @return void
+ */
+ public function outputWithLimit($speed,$download = false){
+ ignore_user_abort(false);
+ $filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
+ set_time_limit(0);
+ session_write_close();
+ if($download){
+ header('Cache-control: private');
+ header('Content-Type: application/octet-stream');
+ header('Content-Length: '.filesize($filePath));
+ $encoded_fname = rawurlencode($this->fileModel["orign_name"]);
+ header('Content-Disposition: attachment;filename="'.$encoded_fname.'";filename*=utf-8'."''".$encoded_fname);
+ ob_flush();
+ flush();
+ }else{
+ header('Content-Type: '.self::getMimetype($filePath));
+ ob_flush();
+ flush();
+ }
+ if(file_exists($filePath)){
+ $fileObj = fopen($filePath,"r");
+ while (!feof($fileObj)){
+ echo fread($fileObj,round($speed*1024));
+ ob_flush();
+ flush();
+ sleep(1);
+ }
+ fclose($fileObj);
+ }
+ }
+
+ /**
+ * 获取文件MIME Type
+ *
+ * @param string $path 文件路径
+ * @return void
+ */
+ static function getMimetype($path){
+ //FILEINFO_MIME will output something like "image/jpeg; charset=binary"
+ $finfoObj = finfo_open(FILEINFO_MIME);
+ $mimetype = finfo_file($finfoObj, $path);
+ finfo_close($finfoObj);
+ return $mimetype;
+ }
+
+ /**
+ * 获取文件MIME Type
+ *
+ * @param string $path 文件路径
+ * @return void
+ */
+ static function getMimetypeOnly($path){
+ //FILEINFO_MIME_TYPE will output something like "image/jpeg"
+ $finfoObj = finfo_open(FILEINFO_MIME_TYPE);
+ $mimetype = finfo_file($finfoObj, $path);
+ finfo_close($finfoObj);
+ return $mimetype;
+ }
+
+ /**
+ * 获取断点续传时HTTP_RANGE头
+ *
+ * @param int $file_size 文件大小
+ * @return void
+ */
+ private function getRange($file_size){
+ if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){
+ $range = $_SERVER['HTTP_RANGE'];
+ $range = preg_replace('/[\s|,].*/', '', $range);
+ $range = explode('-', substr($range, 6));
+ if(count($range)<2){
+ $range[1] = $file_size;
+ }
+ $range = array_combine(array('start','end'), $range);
+ if(empty($range['start'])){
+ $range['start'] = 0;
+ }
+ if(empty($range['end'])){
+ $range['end'] = $file_size;
+ }
+ return $range;
+ }
+ return null;
+ }
+
+ /**
+ * 生成/返回 文件缩略图
+ *
+ * @return array 重定向信息
+ */
+ public function getThumb(){
+ $picInfo = explode(",",$this->fileModel["pic_info"]);
+ $picInfo = self::getThumbSize($picInfo[0],$picInfo[1]);
+ if(file_exists(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb")){
+ self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
+ return [0,0];
+ }
+ $thumbImg = new Thumb(ROOT_PATH . "public/uploads/".$this->fileModel["pre_name"]);
+ $thumbImg->thumb($picInfo[1], $picInfo[0]);
+ if(!is_dir(dirname(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]))){
+ mkdir(dirname(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]),0777,true);
+ }
+ $thumbImg->out(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
+ self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
+ return [0,0];
+ }
+
+ /**
+ * 计算缩略图大小
+ *
+ * @param int $width 原始宽
+ * @param int $height 原始高
+ * @return array
+ */
+ static function getThumbSize($width,$height){
+ $rate = $width/$height;
+ $maxWidth = 90;
+ $maxHeight = 39;
+ $changeWidth = 39*$rate;
+ $changeHeight = 90/$rate;
+ if($changeWidth>=$maxWidth){
+ return [(int)$changeHeight,90];
+ }
+ return [39,(int)$changeWidth];
+ }
+
+ /**
+ * 输出缩略图
+ *
+ * @param string $path 缩略图文件路径
+ * @return void
+ */
+ static function outputThumb($path){
+ ob_end_clean();
+ if(!input("get.cache")=="no"){
+ header("Cache-Control: max-age=10800");
+ }
+ header('Content-Type: '.self::getMimetype($path));
+ $fileObj = fopen($path,"r");
+ echo fread($fileObj,filesize($path));
+ fclose($file);
+ }
+
+ /**
+ * 处理下载请求
+ *
+ * @param boolean $isAdmin 是否为管理员请求
+ * @return void
+ */
+ public function Download($isAdmin=false){
+ $speedLimit = Db::name('groups')->where('id',$this->userModel["user_group"])->find();
+ $rangeTransfer = $speedLimit["range_transfer"];
+ $speedLimit = $speedLimit["speed"];
+ $sendFileOptions = Option::getValues(["download"]);
+ if($sendFileOptions["sendfile"] == "1"){
+ $this->sendFile($speedLimit,$rangeTransfer,true,$sendFileOptions["header"]);
+ }else{
+ if($isAdmin){
+ $speedLimit = "";
+ }
+ if($speedLimit == "0"){
+ exit();
+ }else if(empty($speedLimit)){
+ $this->outputWithoutLimit(true,$rangeTransfer);
+ exit();
+ }else if((int)$speedLimit > 0){
+ $this->outputWithLimit($speedLimit,true);
+ }
+ }
+ }
+
+ /**
+ * 删除指定本地文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function DeleteFile($fileList,$policyData){
+ $fileListTemp = array_column($fileList, 'pre_name');
+ foreach ($fileListTemp as $key => $value) {
+ @unlink(ROOT_PATH . 'public/uploads/'.$value);
+ if(file_exists(ROOT_PATH . 'public/thumb/'.$value."_thumb")){
+ @unlink(ROOT_PATH . 'public/thumb/'.$value."_thumb");
+ }
+ }
+ }
+
+ /**
+ * 签名临时直链,用于Office365预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ $options = Option::getValues(["oss","basic"]);
+ $timeOut = $options["timeout"];
+ $delayTime = time()+$timeOut;
+ $key=$this->fileModel["id"].":".$delayTime.":".md5($this->userModel["user_pass"].$this->fileModel["id"].$delayTime.config("salt"));
+ return [1,$options['siteURL']."Callback/TmpPreview/key/".$key];
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/Mail.php b/application/index/model/Mail.php
index c7eb4dca..07f131c5 100644
--- a/application/index/model/Mail.php
+++ b/application/index/model/Mail.php
@@ -45,13 +45,16 @@ class Mail extends Model{
$mail->Username =$this->smtpUser;
$mail->Password = $this->smtpPass;
$mail->From = $this->fromAdress;
+ $mail->SMTPDebug = 1;
+ $mail->Debugoutput = function($str, $level) {
+ $this->errorMsg .= $str;
+ };
$mail->isHTML(true);
$mail->addAddress($to,$name);
$mail->Subject = $title;
$mail->Body = $content;
$status = $mail->send();
if(!$status){
- $this->errorMsg = $mail->ErrorInfo;
return false;
}
return true;
diff --git a/application/index/model/OnedriveAdapter.php b/application/index/model/OnedriveAdapter.php
new file mode 100644
index 00000000..5091485d
--- /dev/null
+++ b/application/index/model/OnedriveAdapter.php
@@ -0,0 +1,140 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ $this->clinet = new Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $this->policyModel["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($this->policyModel["sk"]),
+ ]);
+ }
+
+ /**
+ * 获取文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ $file = new \Krizalys\Onedrive\File($this->clinet,"/me/drive/root:/".$this->fileModel["pre_name"].":");
+ return $file->fetchContent();
+ }
+
+ /**
+ * 签名预览URL
+ *
+ * @return void
+ */
+ public function Preview($base=null,$name=null){
+ $preview = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":")),true);
+ return [1,$preview["@microsoft.graph.downloadUrl"]];
+ }
+
+ /**
+ * 保存文件内容
+ *
+ * @param string $content 文件内容
+ * @return void
+ */
+ public function saveContent($content){
+ $this->clinet->createFile(rawurldecode($this->fileModel["pre_name"]),"/me/drive/root:/",$content);
+ }
+
+ /**
+ * 计算缩略图大小
+ *
+ * @param int $width 原始宽
+ * @param int $height 原始高
+ * @return array
+ */
+ static function getThumbSize($width,$height){
+ $rate = $width/$height;
+ $maxWidth = 90;
+ $maxHeight = 39;
+ $changeWidth = 39*$rate;
+ $changeHeight = 90/$rate;
+ if($changeWidth>=$maxWidth){
+ return [(int)$changeHeight,90];
+ }
+ return [39,(int)$changeWidth];
+ }
+
+
+ /**
+ * 获取缩略图地址
+ *
+ * @return string 缩略图地址
+ */
+ public function getThumb(){
+ $picInfo = explode(",",$this->fileModel["pic_info"]);
+ $thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]);
+ $thumb = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":/thumbnails")),true);
+ return [1,$thumb["value"][0]["small"]["url"]];
+ }
+
+ /**
+ * 删除某一策略下的指定upyun文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function DeleteFile($fileList,$policyData){
+ $clinet = new Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $policyData["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($policyData["sk"]),
+ ]);
+ foreach (array_column($fileList, 'pre_name') as $key => $value) {
+ $clinet->deleteObject("/me/drive/root:/".rawurlencode($value).":");
+ }
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ $preview = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":")),true);
+ return [1,$preview["@microsoft.graph.downloadUrl"]];
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/OssAdapter.php b/application/index/model/OssAdapter.php
new file mode 100644
index 00000000..d8553a0d
--- /dev/null
+++ b/application/index/model/OssAdapter.php
@@ -0,0 +1,199 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取OSS策略文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ return file_get_contents($this->Preview()[1]);
+ }
+
+ /**
+ * 签名OSS预览URL
+ *
+ * @return void
+ */
+ public function Preview(){
+ if(!$this->policyModel['bucket_private']){
+ $fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
+ return[true,$fileUrl];
+ }else{
+ $accessKeyId = $this->policyModel["ak"];
+ $accessKeySecret = $this->policyModel["sk"];
+ $endpoint = $this->policyModel["url"];
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ return [false,0];
+ }
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
+ try{
+ $signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"));
+ } catch(OssException $e) {
+ return [false,0];
+ }
+ return[true,$signedUrl];
+ }
+ }
+
+ /**
+ * 保存OSS文件内容
+ *
+ * @param string $content 文件内容
+ * @return void
+ */
+ public function saveContent($content){
+ $accessKeyId = $this->policyModel["ak"];
+ $accessKeySecret = $this->policyModel["sk"];
+ $endpoint = "http".ltrim(ltrim($this->policyModel["server"],"https"),"http");
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ die('{ "result": { "success": false, "error": "鉴权失败" } }');
+ }
+ try{
+ $ossClient->putObject($this->policyModel["bucketname"], $this->fileModel["pre_name"], $content);
+ } catch(OssException $e) {
+ die('{ "result": { "success": false, "error": "编辑失败" } }');
+ }
+ }
+
+ /**
+ * 获取缩略图地址
+ *
+ * @return string 缩略图地址
+ */
+ public function getThumb(){
+ if(!$this->policyModel['bucket_private']){
+ $fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?x-oss-process=image/resize,m_lfit,h_39,w_90";
+ return[true,$fileUrl];
+ }else{
+ $accessKeyId = $this->policyModel["ak"];
+ $accessKeySecret = $this->policyModel["sk"];
+ $endpoint = $this->policyModel["url"];
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ return [false,0];
+ }
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
+ try{
+ $signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"),'GET', array("x-oss-process" => 'image/resize,m_lfit,h_39,w_90'));
+ } catch(OssException $e) {
+ return [false,0];
+ }
+ return[true,$signedUrl];
+ }
+ }
+ /**
+ * 删除某一策略下的指定OSS文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function DeleteFile($fileList,$policyData){
+ $accessKeyId = $policyData["ak"];
+ $accessKeySecret = $policyData["sk"];
+ $endpoint = "http".ltrim(ltrim($policyData["server"],"https"),"http");
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ return false;
+ }
+ try{
+ $ossClient->deleteObjects($policyData["bucketname"], array_column($fileList, 'pre_name'));
+ } catch(OssException $e) {
+ return false;
+ }
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ if(!$this->policyModel['bucket_private']){
+ return[true,"/File/OssDownload?url=".urlencode($this->policyModel["url"].$this->fileModel["pre_name"])."&name=".urlencode($this->fileModel["orign_name"])];
+ }else{
+ $accessKeyId = $this->policyModel["ak"];
+ $accessKeySecret = $this->policyModel["sk"];
+ $endpoint = $this->policyModel["url"];
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ return [false,0];
+ }
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
+ try{
+ $signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"),'GET', array("response-content-disposition" => 'attachment; filename='.$this->fileModel["orign_name"]));
+ } catch(OssException $e) {
+ return [false,0];
+ }
+ return[true,$signedUrl];
+ }
+ }
+
+ /**
+ * 删除临时文件
+ *
+ * @param string $fname 文件名
+ * @param array $policy 上传策略信息
+ * @return boolean
+ */
+ static function deleteOssFile($fname,$policy){
+ $accessKeyId = $policy["ak"];
+ $accessKeySecret = $policy["sk"];
+ $endpoint = "http".ltrim(ltrim($policy["server"],"https"),"http");
+ try {
+ $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
+ } catch (OssException $e) {
+ return false;
+ }
+ try{
+ $ossClient->deleteObject($policy["bucketname"], $fname);
+ } catch(OssException $e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/QiniuAdapter.php b/application/index/model/QiniuAdapter.php
new file mode 100644
index 00000000..cfe1eae4
--- /dev/null
+++ b/application/index/model/QiniuAdapter.php
@@ -0,0 +1,149 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ return file_get_contents($this->Preview()[1]);
+ }
+
+ /**
+ * 签名七牛文件预览URL
+ *
+ * @param string $thumb 缩略图参数
+ * @return void
+ */
+ public function Preview($thumb=null){
+ if($thumb===true || $thumb===false){
+ $thumb =null;
+ }
+ if(!$this->policyModel['bucket_private']){
+ $fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"].$thumb;
+ return[true,$fileUrl];
+ }else{
+ $auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"].$thumb;
+ $signedUrl = $auth->privateDownloadUrl($baseUrl);
+ return[true,$signedUrl];
+ }
+ }
+
+ /**
+ * 保存七牛文件内容
+ *
+ * @param string $content 文件内容
+ * @return bool
+ */
+ public function saveContent($content){
+ $auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
+ $expires = 3600;
+ $keyToOverwrite = $this->fileModel["pre_name"];
+ $upToken = $auth->uploadToken($this->policyModel["bucketname"], $keyToOverwrite, $expires, null, true);
+ $uploadMgr = new \Qiniu\Storage\UploadManager();
+ list($ret, $err) = $uploadMgr->put($upToken, $keyToOverwrite, $content);
+ if ($err !== null) {
+ die('{ "result": { "success": false, "error": "编辑失败" } }');
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * 获取缩略图地址
+ *
+ * @return string 缩略图地址
+ */
+ public function getThumb(){
+ return $this->Preview("?imageView2/2/w/90/h/39");
+ }
+
+/**
+ * 删除某一策略下的指定七牛文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function deleteFile($fileList,$policyData){
+ $auth = new Auth($policyData["ak"], $policyData["sk"]);
+ $config = new \Qiniu\Config();
+ $bucketManager = new \Qiniu\Storage\BucketManager($auth);
+ $fileListTemp = array_column($fileList, 'pre_name');
+ $ops = $bucketManager->buildBatchDelete($policyData["bucketname"], $fileListTemp);
+ list($ret, $err) = $bucketManager->batch($ops);
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ if(!$this->policyModel['bucket_private']){
+ $fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?attname=".urlencode($this->fileModel["orign_name"]);
+ return[true,$fileUrl];
+ }else{
+ $auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?attname=".urlencode($this->fileModel["orign_name"]);
+ $signedUrl = $auth->privateDownloadUrl($baseUrl);
+ return[true,$signedUrl];
+ }
+ }
+
+ /**
+ * 删除临时文件
+ *
+ * @param string $fname 文件名
+ * @param array $policy 上传策略信息
+ * @return void
+ */
+ static function deleteSingle($fname,$policy){
+ $auth = new Auth($policy["ak"], $policy["sk"]);
+ $config = new \Qiniu\Config();
+ $bucketManager = new \Qiniu\Storage\BucketManager($auth);
+ $err = $bucketManager->delete($policy["bucketname"], $fname);
+ if ($err) {
+ return false;
+ }else{
+ return true;
+ }
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/RemoteAdapter.php b/application/index/model/RemoteAdapter.php
new file mode 100644
index 00000000..a2d9a334
--- /dev/null
+++ b/application/index/model/RemoteAdapter.php
@@ -0,0 +1,97 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ return file_get_contents($this->Preview()[1]);
+ }
+
+ /**
+ * 签名文件预览URL
+ *
+ * @return void
+ */
+ public function Preview(){
+ $remote = new Remote($this->policyModel);
+ return [1,$remote->preview($this->fileModel["pre_name"])];
+ }
+
+ /**
+ * 保存文件内容
+ *
+ * @param string $content 文件内容
+ * @return bool
+ */
+ public function saveContent($content){
+ $remote = new Remote($this->policyModel);
+ $remote->updateContent($this->fileModel["pre_name"],$content);
+ }
+
+ /**
+ * 获取缩略图地址
+ *
+ * @return string 缩略图地址
+ */
+ public function getThumb(){
+ $remote = new Remote($this->policyModel);
+ return [1,$remote->thumb($this->fileModel["pre_name"],explode(",",$this->fileModel["pic_info"]))];
+ }
+
+/**
+ * 删除某一策略下的指定文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function deleteFile($fileList,$policyData){
+ $remoteObj = new Remote($policyData);
+ $remoteObj->remove(array_column($fileList, 'pre_name'));
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ $remote = new Remote($this->policyModel);
+ return [1,$remote->download($this->fileModel["pre_name"],$this->fileModel["orign_name"])];
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/S3Adapter.php b/application/index/model/S3Adapter.php
new file mode 100644
index 00000000..b9c7a3c0
--- /dev/null
+++ b/application/index/model/S3Adapter.php
@@ -0,0 +1,109 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取又拍云策略文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ return file_get_contents($this->Preview()[1]);
+ }
+
+ /**
+ * 签名S3预览URL
+ *
+ * @return void
+ */
+ public function Preview($base=null,$name=null){
+ if($base===true || $base ===false){
+ $base = null;
+ }
+ $timeOut = Option::getValue("timeout");
+ return [1,\S3\S3::aws_s3_link($this->policyModel["ak"], $this->policyModel["sk"],$this->policyModel["bucketname"],"/".$this->fileModel["pre_name"],3600,$this->policyModel["op_name"])];
+ }
+
+ /**
+ * 保存文件内容
+ *
+ * @param string $content 文件内容
+ * @return void
+ */
+ public function saveContent($content){
+ $s3 = new \S3\S3($this->policyModel["ak"], $this->policyModel["sk"],false,$this->policyModel["op_pwd"]);
+ $s3->setSignatureVersion('v4');
+ $s3->putObjectString($content, $this->policyModel["bucketname"], $this->fileModel["pre_name"]);
+ }
+
+ /**
+ * 删除某一策略下的指定文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function DeleteFile($fileList,$policyData){
+ foreach (array_column($fileList, 'pre_name') as $key => $value) {
+ self::deleteS3File($value,$policyData);
+ }
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ $timeOut = Option::getValue("timeout");
+ return [1,\S3\S3::aws_s3_link($this->policyModel["ak"], $this->policyModel["sk"],$this->policyModel["bucketname"],"/".$this->fileModel["pre_name"],3600,$this->policyModel["op_name"],array(),false)];
+ }
+
+ /**
+ * 删除临时文件
+ *
+ * @param string $fname 文件名
+ * @param array $policy 上传策略信息
+ * @return boolean
+ */
+ static function deleteS3File($fname,$policy){
+ $s3 = new \S3\S3($policy["ak"], $policy["sk"],false,$policy["op_pwd"]);
+ $s3->setSignatureVersion('v4');
+ return $s3->deleteObject($policy["bucketname"],$fname);
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/ShareHandler.php b/application/index/model/ShareHandler.php
index ebbd27cd..876c17b9 100644
--- a/application/index/model/ShareHandler.php
+++ b/application/index/model/ShareHandler.php
@@ -81,6 +81,20 @@ class ShareHandler extends Model{
}
}
+ public function getThumb($user,$path,$folder=false){
+ $checkStatus = $this->checkSession($user);
+ if(!$checkStatus[0]){
+ return [$checkStatus[0],$checkStatus[1]];
+ }
+ $reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
+ if($folder){
+ $fileObj = new FileManage($path,$this->shareData["owner"]);
+ }else{
+ $fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
+ }
+ return $fileObj->getThumb();
+ }
+
public function checkSession($user){
if($this->lockStatus){
return [false,"会话过期,请刷新页面"];
diff --git a/application/index/model/Task.php b/application/index/model/Task.php
new file mode 100644
index 00000000..7c0ffe9e
--- /dev/null
+++ b/application/index/model/Task.php
@@ -0,0 +1,355 @@
+insert([
+ "task_name" => $this->taskName,
+ "attr" => $this->taskContent,
+ "type" => $this->taskType,
+ "status" => "todo",
+ "uid" => $this->userId,
+ ]);
+ }
+
+ /**
+ * 开始执行任务
+ *
+ * @return void
+ */
+ public function Doit(){
+ switch ($this->taskModel["type"]){
+ case "uploadSingleToOnedrive":
+ $this->uploadSingleToOnedrive();
+ break;
+ case "UploadRegularRemoteDownloadFileToOnedrive":
+ $this->uploadSingleToOnedrive();
+ break;
+ case "uploadChunksToOnedrive":
+ $this->uploadChunksToOnedrive();
+ break;
+ case "UploadLargeRemoteDownloadFileToOnedrive":
+ $this->uploadUnchunkedFile();
+ break;
+ default:
+ $this->output->writeln("Unknown task type (".$this->taskModel["type"].")");
+ break;
+ }
+ }
+
+ /**
+ * 上传未分片的大文件至Onedrive
+ *
+ * @return void
+ */
+ private function uploadUnchunkedFile(){
+ $this->taskContent = json_decode($this->taskModel["attr"],true);
+ $policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
+ $this->policyModel = $policyData;
+ $onedrive = new Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $policyData["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($policyData["sk"]),
+ ]);
+
+ //创建分片上传Session,获取上传URL
+ try{
+ $uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpChunk();
+ return;
+ }
+ //创建分片上传Session,获取上传URL
+ try{
+ $uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpChunk();
+ return;
+ }
+
+ //每次4MB上传文件
+
+ if(!$file = @fopen($this->taskContent["originPath"],"r")){
+ $this->status="error";
+ $this->errorMsg = "File not exist.";
+ $this->cleanTmpChunk();
+ return;
+ }
+ $offset = 0;
+ $totalSize = filesize($this->taskContent["originPath"]);
+ while (1) {
+ //移动文件指针
+ fseek($file, $offset);
+
+ $chunksize = (($offset+4*1024*1024)>$totalSize)?($totalSize-$offset):1024*4*1024;
+ $headers = [];
+ $headers[] = "Content-Length: ".$chunksize;
+ $headers[] = "Content-Range: bytes ".$offset."-".($offset+$chunksize-1)."/".$this->taskContent["fsize"];
+
+ //发送单个分片数据
+ try{
+ $onedrive->sendFileChunk($uploadUrl,$headers,fread($file,$chunksize));
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpChunk();
+ return;
+ }
+ $this->output->writeln("[Info] Chunk Uploaded. Offset:".$offset);
+ $offset+=$chunksize;
+ if($offset+1 >=$totalSize){
+ break;
+ }
+
+ }
+ fclose($file);
+ $jsonData = array(
+ "path" => $this->taskContent["path"],
+ "fname" => $this->taskContent["fname"],
+ "objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
+ "fsize" => $this->taskContent["fsize"],
+ );
+
+ $addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
+ if(!$addAction[0]){
+ $this->setError($addAction[1],true,"/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]),$onedrive);
+ $this->cleanTmpChunk();
+ return;
+ }
+
+ $this->cleanTmpChunk();
+
+ }
+
+ /**
+ * 上传已分片的大文件至Onedrive
+ *
+ * @return void
+ */
+ private function uploadChunksToOnedrive(){
+ $this->taskContent = json_decode($this->taskModel["attr"],true);
+ $policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
+ $this->policyModel = $policyData;
+ $onedrive = new Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $policyData["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($policyData["sk"]),
+ ]);
+
+ //创建分片上传Session,获取上传URL
+ try{
+ $uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpChunk();
+ return;
+ }
+
+ //逐个上传文件分片
+ $offset = 0;
+ foreach ($this->taskContent["chunks"] as $key => $value) {
+ $chunkPath = ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk";
+ if(!$file = @fopen($chunkPath,"r")){
+ $this->status="error";
+ $this->errorMsg = "File chunk not exist.";
+ $this->cleanTmpChunk();
+ return;
+ }
+ $headers = [];
+ $chunksize = filesize($chunkPath);
+ $headers[] = "Content-Length: ".$chunksize;
+ $headers[] = "Content-Range: bytes ".$offset."-".($offset+$chunksize-1)."/".$this->taskContent["fsize"];
+
+ //发送单个分片数据
+ try{
+ $onedrive->sendFileChunk($uploadUrl,$headers,$file);
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpChunk();
+ return;
+ }
+ $this->output->writeln("[Info] Chunk Uploaded. Offset:".$offset);
+ $offset += $chunksize;
+ fclose($file);
+
+ }
+
+ $jsonData = array(
+ "path" => $this->taskContent["path"],
+ "fname" => $this->taskContent["fname"],
+ "objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
+ "fsize" => $this->taskContent["fsize"],
+ );
+
+ $addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
+ if(!$addAction[0]){
+ $this->setError($addAction[1],true,"/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]),$onedrive);
+ $this->cleanTmpChunk();
+ return;
+ }
+
+ $this->cleanTmpChunk();
+
+
+ }
+
+ /**
+ * 上传单文件(<=4mb)至Onedrive
+ *
+ * @return void
+ */
+ private function uploadSingleToOnedrive(){
+ $this->taskContent = json_decode($this->taskModel["attr"],true);
+ $policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
+ $this->policyModel = $policyData;
+ $onedrive = new Client([
+ 'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
+ 'client_id' => $policyData["bucketname"],
+
+ // Restore the previous state while instantiating this client to proceed in
+ // obtaining an access token.
+ 'state' => json_decode($policyData["sk"]),
+ ]);
+
+ $filePath = $this->taskModel["type"] == "UploadRegularRemoteDownloadFileToOnedrive"?$this->taskContent["originPath"]:ROOT_PATH . 'public/uploads/'.$this->taskContent["savePath"] . "/" . $this->taskContent["objname"];
+ if($file = @fopen($filePath,"r")){
+ try{
+ $onedrive->createFile(rawurlencode($this->taskContent["objname"]),"/me/drive/root:/".$this->taskContent["savePath"],$file);
+ }catch(\Exception $e){
+ $this->status="error";
+ $this->errorMsg = $e->getMessage();
+ $this->cleanTmpFile();
+ return;
+ }
+
+ $jsonData = array(
+ "path" => $this->taskContent["path"],
+ "fname" => $this->taskContent["fname"],
+ "objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
+ "fsize" => $this->taskContent["fsize"],
+ );
+
+ $addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
+ if(!$addAction[0]){
+ $this->setError($addAction[1],true,"/me/drive/root:/".$this->taskContent["savePath"]."/".rawurlencode($this->taskContent["objname"]),$onedrive);
+ $this->cleanTmpFile();
+ return;
+ }
+
+ fclose($file);
+ $this->cleanTmpFile();
+ }else{
+ $this->status = "error";
+ $this->errorMsg = "Failed to open file [".$filePath."]";
+ }
+
+ }
+
+ /**
+ * 删除本地临时文件
+ *
+ * @return bool 是否成功
+ */
+ private function cleanTmpFile(){
+ if($this->taskModel["type"] == "UploadRegularRemoteDownloadFileToOnedrive"){
+ return @unlink($this->taskContent["originPath"]);
+ }else{
+ return @unlink(ROOT_PATH . 'public/uploads/'.$this->taskContent["savePath"] . "/" . $this->taskContent["objname"]);
+ }
+
+ }
+
+ /**
+ * 删除本地临时分片
+ *
+ * @return void
+ */
+ private function cleanTmpChunk(){
+ if($this->taskModel["type"] == "UploadLargeRemoteDownloadFileToOnedrive"){
+ @unlink($this->taskContent["originPath"]);
+ }else{
+ foreach ($this->taskContent["chunks"] as $key => $value) {
+ @unlink( ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
+ }
+ }
+ }
+
+ /**
+ * 设置为出错状态并清理远程文件
+ *
+ * @param string $msg 错误消息
+ * @param bool $delete 是否删除文件
+ * @param string $path 文件路径
+ * @param mixed $adapter 远程操作适配器
+ * @return void
+ */
+ private function setError($msg,$delete,$path,$adapter){
+ $this->status="error";
+ $this->errorMsg = $msg;
+ if($delete){
+ switch($this->taskModel["type"]){
+ case "uploadSingleToOnedrive":
+ $adapter->deleteObject($path);
+ break;
+ case "uploadChunksToOnedrive":
+ $adapter->deleteObject($path);
+ break;
+ default:
+
+ break;
+ }
+ }
+ FileManage::storageGiveBack($this->taskModel["uid"],$this->taskContent["fsize"]);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/UploadHandler.php b/application/index/model/UploadHandler.php
index 671e260e..e209f80c 100644
--- a/application/index/model/UploadHandler.php
+++ b/application/index/model/UploadHandler.php
@@ -8,6 +8,7 @@ use think\Db;
use Qiniu\Auth;
use \app\index\model\Option;
use \app\index\model\FileManage;
+use \app\index\model\Task;
class UploadHandler extends Model{
@@ -75,13 +76,25 @@ class UploadHandler extends Model{
return 0;
}
+ /**
+ * 组合分片并生成最终文件
+ *
+ * @param array $ctx 文件片校验码
+ * @param string $fname 最终文件名
+ * @param string $path 储存目录
+ * @return void
+ */
public function generateFile($ctx,$fname,$path){
$ctxTmp = explode(",",$ctx);
$chunks = Db::name('chunks')->where([
'ctx' => ["in",$ctxTmp],
])->order('id asc')->select();
- $file = $this->combineChunks($chunks);
- $this->filterCheck($file,$fname);
+ $file = null;
+ if($this->policyContent["policy_type"] != "onedrive"){
+ $file = $this->combineChunks($chunks);
+ }
+
+ $this->filterCheck($file,$fname,$chunks);
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
if($this->policyContent['autoname']){
@@ -95,28 +108,67 @@ class UploadHandler extends Model{
if(file_exists($savePath.DS.$fileName)){
$this->setError("文件重名",true,$file,ROOT_PATH . 'public/uploads/chunks/');
}
- if(!@rename(ROOT_PATH . 'public/uploads/chunks/'.$file,$savePath.DS.$fileName)){
- $this->setError("文件创建失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
- }else{
+ if($this->policyContent["policy_type"] == "onedrive"){
if($path == "ROOTDIR"){
$path = "";
}
- $jsonData = array(
+ $task = new Task();
+ $task->taskName = "Upload Big File " . $fname . " to Onedrive";
+ $task->taskType = "uploadChunksToOnedrive";
+ $task->taskContent = json_encode([
"path" => $path,
"fname" => $fname,
- "objname" => $generatePath."/".$fileName,
+ "objname" => $fileName,
+ "savePath" => $generatePath,
"fsize" => $this->fileSizeTmp,
- );
- $addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId);
+ "picInfo" => "",
+ "chunks" => $chunks,
+ "policyId" => $this->policyContent['id']
+ ]);
+ $task->userId = $this->userId;
+ $task->saveTask();
+ echo json_encode(array("key" => $fname));
+ }else{
+ if(!@rename(ROOT_PATH . 'public/uploads/chunks/'.$file,$savePath.DS.$fileName)){
+ $this->setError("文件创建失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
+ }else{
+ if($path == "ROOTDIR"){
+ $path = "";
+ }
+ $jsonData = array(
+ "path" => $path,
+ "fname" => $fname,
+ "objname" => $generatePath."/".$fileName,
+ "fsize" => $this->fileSizeTmp,
+ );
+ @list($width, $height, $type, $attr) = getimagesize($savePath.DS.$fileName);
+ $picInfo = empty($width)?" ":$width.",".$height;
+ $addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId,$picInfo);
if(!$addAction[0]){
$this->setError($addAction[1],true,$fileName,$savePath);
}
- echo json_encode(array("key" => $fname));
+ echo json_encode(array("key" => $fname));
+ }
}
+
}
- public function filterCheck($file,$fname){
- $fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
+ protected function countTotalChunkSize($chunks){
+ $size = 0;
+ foreach ($chunks as $key => $value) {
+ $size += @filesize(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
+ }
+
+ return $size;
+ }
+
+ public function filterCheck($file,$fname,$chunks){
+ if($file !=null){
+ $fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
+ }else{
+ $fileSize = $this->countTotalChunkSize($chunks);
+ }
+
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
$allowedSuffix = explode(',', self::getAllowedExt(json_decode($this->policyContent["filetype"],true)));
@@ -131,6 +183,12 @@ class UploadHandler extends Model{
$this->fileSizeTmp = $fileSize;
}
+ /**
+ * 组合文件分片
+ *
+ * @param array $fname 文件分片数据库记录
+ * @return void
+ */
public function combineChunks($fname){
$fileName = "file_".self::getRandomKey(8);
$fileObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$fileName,"a+");
@@ -181,12 +239,39 @@ class UploadHandler extends Model{
);
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$Uploadinfo->getSaveName());
$picInfo = empty($width)?" ":$width.",".$height;
+
+ //处理Onedrive等非直传
+ if($this->policyContent['policy_type'] == "onedrive"){
+ $task = new Task();
+ $task->taskName = "Upload" . $info["name"] . " to Onedrive";
+ $task->taskType = "uploadSingleToOnedrive";
+ $task->taskContent = json_encode([
+ "path" => $info["path"],
+ "fname" => $info["name"],
+ "objname" => $Uploadinfo->getSaveName(),
+ "savePath" => $generatePath,
+ "fsize" => $Uploadinfo->getSize(),
+ "picInfo" => $picInfo,
+ "policyId" => $this->policyContent['id']
+ ]);
+ $task->userId = $this->userId;
+
+ $task->saveTask();
+
+ echo json_encode(array("key" => $info["name"]));
+ FileManage::storageCheckOut($this->userId,$jsonData["fsize"],$Uploadinfo->getInfo('size'));
+ return;
+ }
+
+ //向数据库中添加文件记录
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId,$picInfo);
if(!$addAction[0]){
$tmpFileName = $Uploadinfo->getSaveName();
unset($Uploadinfo);
$this->setError($addAction[1],true,$tmpFileName,$savePath);
}
+
+ //扣除容量
FileManage::storageCheckOut($this->userId,$jsonData["fsize"],$Uploadinfo->getInfo('size'));
echo json_encode(array("key" => $info["name"]));
}else{
@@ -219,6 +304,9 @@ class UploadHandler extends Model{
case 'local':
return $this->getLocalToken();
break;
+ case 'onedrive':
+ return 'nazGTT91tboaLWBC549$:tHSsNyTBxoV4HDfELJeKH1EUmEY=:eyJjYWxsYmFja0JvZHkiOiJ7XCJwYXRoXCI6XCJcIn0iLCJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb25cL2pzb24iLCJzY29wZSI6ImMxNjMyMTc3LTQ4NGEtNGU1OS1hZDBhLWUwNDc4ZjZhY2NjZSIsImRlYWRsaW5lIjoxNTM2ODMxOTEwfQ==';
+ break;
case 'oss':
return $this->getOssToken();
break;
diff --git a/application/index/model/UpyunAdapter.php b/application/index/model/UpyunAdapter.php
new file mode 100644
index 00000000..4ef091ed
--- /dev/null
+++ b/application/index/model/UpyunAdapter.php
@@ -0,0 +1,162 @@
+fileModel = $file;
+ $this->policyModel = $policy;
+ $this->userModel = $user;
+ }
+
+ /**
+ * 获取又拍云策略文本文件内容
+ *
+ * @return string 文件内容
+ */
+ public function getFileContent(){
+ return file_get_contents($this->Preview()[1]);
+ }
+
+ /**
+ * 签名又拍云预览URL
+ *
+ * @return void
+ */
+ public function Preview($base=null,$name=null){
+ if($base===true || $base===false){
+ $base =null;
+ }
+ if(!$this->policyModel['bucket_private']){
+ $fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?auth=0";
+ if(!empty($base)){
+ $fileUrl = $base;
+ }
+ return[true,$fileUrl];
+ }else{
+ $baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
+ if(!empty($base)){
+ $baseUrl = $base;
+ }
+ $etime = time() + Option::getValue("timeout");
+ $key = $this->policyModel["sk"];
+ $path = "/".$this->fileModel["pre_name"];
+ if(!empty($name)){
+ $path = "/".$name;
+ }
+ $sign = substr(md5($key.'&'.$etime.'&'.$path), 12, 8).$etime;
+ $signedUrl = $baseUrl."?_upt=".$sign;
+ return[true,$signedUrl];
+ }
+ }
+
+ /**
+ * 保存文件内容
+ *
+ * @param string $content 文件内容
+ * @return void
+ */
+ public function saveContent($content){
+ $bucketConfig = new Config($this->policyModel["bucketname"], $this->policyModel["op_name"], $this->policyModel["op_pwd"]);
+ $client = new Upyun($bucketConfig);
+ if(empty($content)){
+ $content = " ";
+ }
+ $res=$client->write($this->fileModel["pre_name"],$content);
+ }
+
+ /**
+ * 计算缩略图大小
+ *
+ * @param int $width 原始宽
+ * @param int $height 原始高
+ * @return array
+ */
+ static function getThumbSize($width,$height){
+ $rate = $width/$height;
+ $maxWidth = 90;
+ $maxHeight = 39;
+ $changeWidth = 39*$rate;
+ $changeHeight = 90/$rate;
+ if($changeWidth>=$maxWidth){
+ return [(int)$changeHeight,90];
+ }
+ return [39,(int)$changeWidth];
+ }
+
+
+ /**
+ * 获取缩略图地址
+ *
+ * @return string 缩略图地址
+ */
+ public function getThumb(){
+ $picInfo = explode(",",$this->fileModel["pic_info"]);
+ $thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]);
+ $baseUrl =$this->policyModel["url"].$this->fileModel["pre_name"]."!/fwfh/90x39";
+ return [1,$this->Preview($baseUrl,$this->fileModel["pre_name"]."!/fwfh/90x39")[1]];
+ }
+
+ /**
+ * 删除某一策略下的指定upyun文件
+ *
+ * @param array $fileList 待删除文件的数据库记录
+ * @param array $policyData 待删除文件的上传策略信息
+ * @return void
+ */
+ static function DeleteFile($fileList,$policyData){
+ foreach (array_column($fileList, 'pre_name') as $key => $value) {
+ self::deleteUpyunFile($value,$policyData);
+ }
+ }
+
+ /**
+ * 生成文件下载URL
+ *
+ * @return array
+ */
+ public function Download(){
+ return [true,$this->Preview()[1]."&_upd=".urlencode($this->fileModel["orign_name"])];
+ }
+
+ /**
+ * 删除临时文件
+ *
+ * @param string $fname 文件名
+ * @param array $policy 上传策略信息
+ * @return boolean
+ */
+ static function deleteUpyunFile($fname,$policy){
+ $bucketConfig = new Config($policy["bucketname"], $policy["op_name"], $policy["op_pwd"]);
+ $client = new Upyun($bucketConfig);
+ $res=$client->delete($fname,true);
+ }
+
+ /**
+ * 签名临时URL用于Office预览
+ *
+ * @return array
+ */
+ public function signTmpUrl(){
+ return $this->Preview();
+ }
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/application/index/model/User.php b/application/index/model/User.php
index 49d9370c..0a87ad6f 100644
--- a/application/index/model/User.php
+++ b/application/index/model/User.php
@@ -308,8 +308,8 @@ class User extends Model{
public function getMemory($notEcho = false){
$usedMemory = $this->userSQLData["used_storage"];
- $groupStorage = (int)$this->groupData["max_storage"];
- $packetStorage = (int)Db::name('storage_pack')
+ $groupStorage = $this->groupData["max_storage"];
+ $packetStorage = Db::name('storage_pack')
->where('uid',$this->uid)
->where('dlay_time',">",time())
->sum('pack_size');
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协议同步文件。目前此功能仅支持本地上传方案
+
+
+
+
+

+
+
Onedrive 中转
+
支持 Onedrive Bussiness 和个人版。配置说明
+
添加
+
+
+
diff --git a/application/index/view/admin/add_policy_onedrive.html b/application/index/view/admin/add_policy_onedrive.html
new file mode 100644
index 00000000..56e397b7
--- /dev/null
+++ b/application/index/view/admin/add_policy_onedrive.html
@@ -0,0 +1,155 @@
+{extend name="header_admin" /}
+{block name="title"}添加上传策略- {$options.siteName}{/block}
+{block name="content"}
+
+
+
+
+ -
+ 管理面板
+
+ -
+ 上传策略
+
+ - 添加
+
+
+
+
+
+
添加上传策略
+
+
+
+
添加Onedrive上传策略前请确保阅读完下面内容!
+
+ - Onedrive策略无法直传,上传文件时,Cloudreve会先将文件暂存在服务器,之后再由任务队列上传至Onedrive;
+ - 使用本策略前,请先配置并运行Cloudreve任务队列,否则正常无法使用;
+ - 用户上传文件后不能立马看到所上传的文件,需要等待任务队列处理完毕;
+ - 请确保已经正确配置好Cloudreve的Cron定时任务,以便用于刷新AccessToken信息。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{/block}
+{block name="js"}
+
+{/block}
\ No newline at end of file
diff --git a/application/index/view/admin/download.html b/application/index/view/admin/download.html
new file mode 100644
index 00000000..add5692b
--- /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"}
+
+
+
+
+ -
+ 管理面板
+
+ - 离线下载
+ - 配置
+
+
+
+
+
+
离线下载
+
+
+
+
+
+
+
+
+
+
+
+ # |
+ 文件名 |
+ 创建者 |
+ 文件大小 |
+ 状态 |
+ 进度 |
+ 操作 |
+
+
+
+ {volist name='list' id='download'}
+
+ {$download.id} |
+ {:$originList[$key]['fileName']} |
+ {:$originList[$key]['user']["user_nick"]} |
+ {:countSize($download.total_size)} |
+ {$download.status} |
+ {eq name="$originList[$key]['totalLength']" value="0"}-{else/}{:floor($originList[$key]['completedLength']/$originList[$key]['totalLength']*10000)/100}%{/eq} |
+ {eq name="download.status" value="active"}取消任务{else/} - {/eq} |
+
+ {/volist}
+
+
+
+ {$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..ad678ec2 100644
--- a/application/index/view/admin/edit_group.html
+++ b/application/index/view/admin/edit_group.html
@@ -114,6 +114,18 @@
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+
diff --git a/application/index/view/admin/policy_list.html b/application/index/view/admin/policy_list.html
index 9ad84000..f02c990d 100644
--- a/application/index/view/admin/policy_list.html
+++ b/application/index/view/admin/policy_list.html
@@ -45,6 +45,9 @@
远程
+
+ Onedrive
+
@@ -82,6 +85,7 @@
{case value="upyun"}又拍云{/case}
{case value="s3"}Amazon S3{/case}
{case value="remote"}远程{/case}
+ {case value="onedrive"}Onedrive{/case}
{default /}其他
{/switch}
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 @@
分享
+
+
+
+ 离线下载
+
+
diff --git a/application/index/view/home/Download.html b/application/index/view/home/Download.html
new file mode 100644
index 00000000..7caf3f7d
--- /dev/null
+++ b/application/index/view/home/Download.html
@@ -0,0 +1,81 @@
+{extend name="header_home" /}
+{block name="title"}离线下载管理- {$options.siteName}{/block}
+{block name="content"}
+
+
+
+
+
+ {include file="navbar_home" /}
+
+
+
离线下载管理
+
+
+
+
+
+
+
正在进行中
+
+ 更新状态数据中...
+
+
+
+
+
+ # |
+ 文件名 |
+ 大小 |
+ 储存位置 |
+ 下载速度 |
+ 进度 |
+ 操作 |
+
+
+
+
+
+
+
+
+
+
+
已完成
+
+
+
+
+ # |
+ 文件名 |
+ 大小 |
+ 储存位置 |
+ 状态 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {$options.js_code}
+