/** * 静态方法, 单例统一访问入口 * @return object 返回对象的唯一实例 */ public static function getInstance() { if (is_null(self::$_instance) || !isset(self::$_instance)) { self::$_instance = new self(); } return self::$_instance; }
/** * 获取当前文件版本列表 * @param $path * @return mixed */ public function getList($path) { $item = explode("/", $path); $permissionArr = UserPermissionBiz::getInstance()->getPermission($path, $this->user['id']); if ($item[1] !== $this->user['id'] && count($permissionArr) == 0) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR), MConst::HTTP_CODE_400); } $file = MiniFile::getInstance()->getByPath($path); $version_id = $file['version_id']; $fileMeta = MiniFileMeta::getInstance()->getFileMeta($path, "version"); $fileVersion = MiniVersion::getInstance()->getVersion($version_id); $currentSignature = $fileVersion['file_signature']; $historyArr = array_reverse(unserialize($fileMeta['meta_value'])); // 去掉delete事件版本 $histories = array(); foreach ($historyArr as $item) { $history = array(); if ($item['type'] == CConst::DELETE) { continue; } $history['type'] = $item['type']; $history['file_size'] = $item['file_size']; $history['user_nick'] = $item['user_nick']; $history['device_name'] = $item['device_name']; $history['datetime'] = MiniUtil::formatTime(strtotime($item['datetime'])); $fileVersion = MiniVersion::getInstance()->getVersion($item['version_id']); $history['signature'] = $fileVersion['file_signature']; array_push($histories, $history); } $data['histories'] = $histories; $data['current_signature'] = $currentSignature; return $data; }
/** * 为文件增加冗余备份节点 * @param $signature * @param $nodeId */ public function addReplicateNode($signature, $nodeId) { $version = MiniVersion::getInstance()->getBySignature($signature); if (!empty($version)) { $meta = FileVersionMeta::model()->find("version_id=:version_id and meta_key='store_id'", array("version_id" => $version["id"])); if (isset($meta)) { $value = $meta->meta_value; $isExist = false; $ids = explode(",", $value); foreach ($ids as $id) { if ($id === $nodeId) { $isExist = true; } } if (!$isExist) { $value .= "," . $nodeId; $meta->meta_value = $value; $meta->save(); $ids = explode(",", $value); if (count($ids) >= 3) { //整个文件冗余备份成功 PluginMiniStoreVersion::getInstance()->replicateSuccess($signature); } } } else { $meta = new FileVersionMeta(); $meta->version_id = $version["id"]; $meta->meta_value = $nodeId; $meta->save(); } } }
/** * * 检查文件data和 meta是否存在 */ protected function handleCheckFileVersion($hash) { $version = MiniVersion::getInstance()->getBySignature($hash); if ($version === NULL) { $version = MiniVersion::getInstance()->create($hash, $this->size, $this->type); } $this->version_id = $version["id"]; $this->file_hash = $version["file_signature"]; return true; }
/** * 迷你存储报俊 * @param string $path 用户文件的存储路径 * @param string $signature 文件sha1 * @param int $size 文件大小,单位字节 * @param int $nodeId 迷你存储节点值 */ public function report($path, $signature, $size, $nodeId) { //防止重复文件通过网页上传,生成多条记录 $version = MiniVersion::getInstance()->getBySignature($signature); if (empty($version)) { //创建version/versionMeta数据 $pathParts = pathinfo($path); $type = MiniUtil::getMimeType($pathParts["basename"]); $version = MiniVersion::getInstance()->create($signature, $size, $type); MiniVersionMeta::getInstance()->create($version["id"], "store_id", $nodeId); //更新迷你存储节点状态,把新上传的文件数+1 PluginMiniStoreNode::getInstance()->newUploadFile($nodeId); //清理垃圾数据 PluginMiniBreakFile::getInstance()->deleteBySignature($signature); } //执行文件秒传逻辑 $filesController = new MFileSecondsController(); $filesController->invoke(); }
/** *给迷你云报告文件转换过程 * @param int $nodeId 文档转换服务器Id * @param string $signature 文件hash值 * @param string $status 文件状态 * @return array */ public function report($nodeId, $signature, $status) { $version = MiniVersion::getInstance()->getBySignature($signature); if (!empty($version)) { //文件转换成功 if ($status === "1") { //更新迷你存储节点状态,把新上传的文件数+1 PluginMiniDocNode::getInstance()->newConvertFile($nodeId); PluginMiniDocVersion::getInstance()->updateDocConvertStatus($nodeId, $signature, 2); //通过回调方式让迷你搜索把文件文本内容编制索引到数据库中 do_action("pull_text_search", $signature); } //文件转换失败 if ($status === "0") { PluginMiniDocVersion::getInstance()->updateDocConvertStatus($nodeId, $signature, -1); } } return array("success" => true); }
/** * 全文检索 * @param string $key 关键字 * @param string $path 路径 * @return array */ public function search($key, $path) { $siteId = MiniSiteUtils::getSiteID(); $searchItems = $this->searchKeyWordAndSiteId($siteId, $key); $values = array(); foreach ($searchItems as $searchItem) { //遍历,查询文件signature,根据signature判断当前用户有无浏览该文件权限 $version = MiniVersion::getInstance()->getBySignature($searchItem["signature"]); //反向查询系统所有的文件记录 $fileList = MiniFile::getInstance()->getAllByVersionId($version["id"]); foreach ($fileList as $file) { //对具有相同signature的文件进行过滤 $filePath = $file['file_path']; $isInString = strpos($filePath, $path); if ($isInString === false) { continue; } $userId = (int) $this->user['id']; $permission = UserPermissionBiz::getInstance()->getPermission($filePath, $userId); if ($permission['permission'] == '000000000' || $permission['permission'] == '011111111') { //没有读权限则不显示出来 continue; } if (empty($permission)) { //如果上面读权限为空,则说明没有共享,这时当前用户只能看见自己的文件 $pathArr = explode('/', $filePath); $masterId = $pathArr[1]; if ($masterId != $userId) { continue; } } $item = array(); $item['signature'] = $searchItem["signature"]; //相同的signature可能对应多个文件 $item['file_name'] = $file['file_name']; $item['file_path'] = $filePath; $item['summary'] = $searchItem["summary"]; array_push($values, $item); } } return $values; }
/** * 控制器执行主逻辑函数, 处理移动文件或者文件夹 * * @return mixed $value 返回最终需要执行完的结果 */ public function invoke($uri = null) { // 调用父类初始化函数,注册自定义的异常和错误处理逻辑 parent::init(); $this->setAction(MConst::MOVE); $params = $_REQUEST; // 检查参数 if (isset($params) === false) { throw new MException(Yii::t('api', 'Bad Request 7')); } // // 获取用户数据,如user_id $user = MUserManager::getInstance()->getCurrentUser(); $device = MUserManager::getInstance()->getCurrentDevice(); $this->_userId = $user["user_id"]; $this->master = $user["user_id"]; $user_nick = $user["user_name"]; $user_device_id = $device["device_id"]; $this->_user_device_name = $device["user_device_name"]; // 文件大小格式化参数 $this->_locale = "bytes"; if (isset($params["locale"])) { $this->_locale = $params["locale"]; } if (isset($params["root"]) === false || isset($params["from_path"]) === false || isset($params["to_path"]) === false) { throw new MFileopsException(Yii::t('api', 'Bad Request'), MConst::HTTP_CODE_400); } $this->_root = $params["root"]; $from_path = $params["from_path"]; $to_path = $params["to_path"]; $arr = explode('/', $from_path); $isRoot = false; $isMine = false; if (count($arr) == 3) { $isRoot = true; } $fileOwnerId = $arr[1]; $currentUserId = $this->_userId; if ($fileOwnerId == $currentUserId) { $isMine = true; } if ($isRoot && !$isMine) { //如果是在根目录下且不是自己的目录 则后台控制不准取消共享 throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_409); } $to_parts = explode('/', $to_path); $from_parts = explode('/', $from_path); if (count($to_parts) == 2) { $to_path = '/' . $this->_userId . $to_path; } $to_parts = explode('/', $to_path); $file = MiniFile::getInstance()->getByPath($from_path); $isSelfFile = false; if (!empty($file) && $file['user_id'] == $this->_userId) { $isSelfFile = true; } // 转换路径分隔符,便于以后跨平台,如:将 "\"=>"/" $from_path = MUtils::convertStandardPath($from_path); $to_path = MUtils::convertStandardPath($to_path); if ($to_path[strlen($to_path) - 1] == "/") { // 目标文件无效,403 error throw new MFileopsException(Yii::t('api', 'The file or folder name is invalid'), MConst::HTTP_CODE_403); } // 检查共享 $this->from_share_filter = MSharesFilter::init(); $this->to_share_filter = MSharesFilter::init(); $isSharedPath = true; $this->rename = false; // 检查移动方式 if ($this->rename == true) { // 先copy再删除,如果是移动共享文件夹则只copy,再执行shareManager取消共享 $copy_handler = new MCopyController(); $copy_handler->isOutput = false; $response = $copy_handler->invoke(); $_REQUEST['path'] = $params["from_path"]; $delete_handler = new MDeleteController(); $delete_handler->isOutput = false; $delete_handler->completely_remove = true; $delete_handler->invoke(); if (MUserManager::getInstance()->isWeb() === true) { $this->buildWebResponse(); exit; return; } echo json_encode($response); return; } $file_name = MUtils::get_basename($to_path); // 检查文件名是否有效 $is_invalid = MUtils::checkNameInvalid($file_name); if ($is_invalid) { throw new MFileopsException(Yii::t('api', 'The file or folder name is invalid'), MConst::HTTP_CODE_400); } // 检查是否移动到其子目录下 if (strpos($to_path, $from_path . "/") === 0) { throw new MFileopsException(Yii::t('api', 'Can not be moved to the subdirectory'), MConst::HTTP_CODE_403); } if ($to_path == "/{$this->_userId}" || $to_path == "/{$this->_userId}/") { throw new MFileopsException(Yii::t('api', 'Can not be moved to the error directory'), MConst::HTTP_CODE_403); } $from_parent = CUtils::pathinfo_utf($from_path); $to_parent = CUtils::pathinfo_utf($to_path); $privilegeModel = new PrivilegeBiz(); if (!(count($to_parts) == 3)) { $isSharedPath = false; $toPathArr = explode('/', $to_path); $masterId = $toPathArr[1]; if ($masterId != $this->_userId) { $isSharedPath = true; } else { $model = new GeneralFolderPermissionBiz($to_parent['dirname']); if ($model->isParentShared($to_parent['dirname'])) { //如果是父目录被共享 $isSharedPath = true; } } if ($isSharedPath) { $toPrivilege = UserPermissionBiz::getInstance()->getPermission($to_parent['dirname'], $this->_userId); if (empty($toPrivilege)) { $toPrivilege['permission'] = MConst::SUPREME_PERMISSION; } else { $this->to_share_filter->slaves = $privilegeModel->getSlaveIdsByPath($toPrivilege['share_root_path']); $this->to_share_filter->is_shared = true; } } else { $toPrivilege['permission'] = MConst::SUPREME_PERMISSION; } $toFilter = new MiniPermission($toPrivilege['permission']); } else { if ($to_parent['dirname'] == $from_parent['dirname']) { $isSharedPath = false; $fromPathArr = explode('/', $from_path); $masterId = $fromPathArr[1]; if ($masterId != $this->_userId) { $isSharedPath = true; } else { $model = new GeneralFolderPermissionBiz($from_path); if ($model->isParentShared($from_path)) { //如果是父目录被共享 $isSharedPath = true; } } if ($isSharedPath) { $toPrivilege = UserPermissionBiz::getInstance()->getPermission($from_path, $this->_userId); if (!empty($toPrivilege)) { $this->to_share_filter->slaves = $privilegeModel->getSlaveIdsByPath($toPrivilege['share_root_path']); $this->to_share_filter->is_shared = true; } else { $toPrivilege['permission'] = MConst::SUPREME_PERMISSION; } } else { $toPrivilege['permission'] = MConst::SUPREME_PERMISSION; } } $toFilter = new MiniPermission(MConst::SUPREME_PERMISSION); } $isSharedPath = false; $fromPathArr = explode('/', $from_path); $masterId = $fromPathArr[1]; if ($masterId != $this->_userId) { $isSharedPath = true; } else { $model = new GeneralFolderPermissionBiz($from_path); if ($model->isParentShared($from_path)) { //如果是父目录被共享 $isSharedPath = true; } } if ($isSharedPath) { $fromPrivilege = UserPermissionBiz::getInstance()->getPermission($from_path, $this->_userId); if (empty($fromPrivilege)) { $fromPrivilege['permission'] = MConst::SUPREME_PERMISSION; } else { $this->from_share_filter->slaves = $privilegeModel->getSlaveIdsByPath($fromPrivilege['share_root_path']); $this->from_share_filter->is_shared = true; } } else { $fromPrivilege['permission'] = MConst::SUPREME_PERMISSION; } $fromFilter = new MiniPermission($fromPrivilege['permission']); if ($to_parent['dirname'] == $from_parent['dirname']) { $this->setAction(MConst::RENAME); $this->isRename = true; $canRenameFile = $fromFilter->canModifyFileName(); $canRenameFolder = $fromFilter->canModifyFolderName(); $canRenameFile2 = $toFilter->canModifyFileName(); $canRenameFolder2 = $toFilter->canModifyFolderName(); if ($file['file_type'] > 0 && !$canRenameFolder && !$isSelfFile) { //如果目标是目录,则当其不为己文件,且无更名权限时 exception throw new MFileopsException(Yii::t('api', 'have no permission to rename folder'), MConst::HTTP_CODE_409); } if ($file['file_type'] == 0 && !$canRenameFile && !$isSelfFile) { //如果目标是文件,则当其不为己文件,且无更名权限时 exception throw new MFileopsException(Yii::t('api', 'have no permission to rename file'), MConst::HTTP_CODE_409); } if ($file['file_type'] > 0 && !$canRenameFolder2 && !$isSelfFile) { //如果目标是目录,则当其不为己文件,且无更名权限时 exception throw new MFileopsException(Yii::t('api', 'have no permission to rename folder'), MConst::HTTP_CODE_409); } if ($file['file_type'] == 0 && !$canRenameFile2 && !$isSelfFile) { //如果目标是文件,则当其不为己文件,且无更名权限时 exception throw new MFileopsException(Yii::t('api', 'have no permission to rename file'), MConst::HTTP_CODE_409); } } else { $canDeleteFile = $fromFilter->canDeleteFile(); $canDeleteFile2 = $toFilter->canDeleteFile(); if (!$canDeleteFile || !$canDeleteFile2) { throw new MFileopsException(Yii::t('api', 'have no permission to move file'), MConst::HTTP_CODE_409); } } // 先检查源目录是否存在,如果不存在抛出404错误 // $query_db_file = MFiles::queryFilesByPath($from_path); if ($query_db_file === false || empty($query_db_file)) { throw new MFileopsException(Yii::t('api', 'The source file was not found at the specified path'), MConst::HTTP_CODE_404); } // // 检查目标是否存在(包括已被删除的状态) // $deleted = null; $query_db_goal_file = MFiles::queryAllFilesByPath($to_path); if ($query_db_goal_file) { if ($from_path !== $to_path && $query_db_goal_file[0]["is_deleted"] == false) { throw new MFileopsException(Yii::t('api', 'There is already a item at the given destination'), MConst::HTTP_CODE_403); } // 已删除文件的处理 if ($query_db_goal_file[0]["is_deleted"] == 1) { MFiles::deleteById($query_db_goal_file[0]["id"]); if ($query_db_goal_file[0]["file_type"] != 0) { // 文件则直接删除 $deleted = $query_db_goal_file[0]["id"]; } } } $query_db_file = MFiles::queryFilesByPath($from_path); if ($query_db_file === false || empty($query_db_file)) { throw new MFileopsException(Yii::t('api', 'Not found the source files of the specified path'), MConst::HTTP_CODE_404); } // // 检查移动原路径与目标路径是否一致,一致则则返回其文件信息 // if ($from_path === $to_path) { $this->buildResult($query_db_file[0]); return; } // // 查询目标路径父目录信息 // $pathInfo = MUtils::pathinfo_utf($to_path); $parent_path = $pathInfo["dirname"]; $create_folder = new MCreateFolderController(); $create_folder->_user_device_id = $user_device_id; $create_folder->_user_id = $this->_userId; if (count(explode('/', $parent_path)) == 2) { $parent_file_id = 0; } else { $parent_file_id = $create_folder->handlerParentFolder($parent_path); } $fromUserId = $from_parts[1]; $toUserId = $to_parts[1]; // // 组装对象信息 // $file_detail = new MFiles(); $file_detail->file_name = $file_name; $file_detail->file_path = $to_path; $file_detail->file_type = $query_db_file[0]["file_type"]; $file_detail->id = $query_db_file[0]["id"]; $file_detail->from_path = $from_path; $file_detail->parent_file_id = $parent_file_id; $file_detail->user_id = $toUserId; $file_detail->mime_type = NULL; $create_array = array(); // // 判断操作的是文件夹,还是文件 // if ($file_detail->file_type > MConst::OBJECT_TYPE_FILE) { if ($file['user_id'] != $this->_userId) { $updateUserId = $query_db_file[0]["user_id"]; } else { $updateUserId = $this->master; } // // 文件夹,将会对其子文件做进一步处理 // $ret_value = MFiles::updateMoveChildrenFileDetail($updateUserId, $file_detail); if ($ret_value === false) { throw new MFileopsException(Yii::t('api', 'Not found the source files of the specified path'), MConst::HTTP_CODE_404); } // // 针对文件夹下的文件,组装需要添加版本信息的文件 // $create_array = $this->handleChildrenVersions($create_array, $this->_userId, $user_nick, $from_path, $to_path, $query_db_file[0]["id"], $this->_user_device_name, $query_db_file[0]["file_size"]); } else { $file_detail->mime_type = MiniUtil::getMimeType($file_name); $file_meta = new MFileMetas(); $file_meta->version_id = $query_db_file[0]["version_id"]; // // 查询之前是否包含其版本 // $file_version = MFileMetas::queryFileMeta($to_path, MConst::VERSION); if ($file_version) { $meta_value = MUtils::getFileVersions($this->_user_device_name, $query_db_file[0]['file_size'], $file_meta->version_id, MConst::CREATE_FILE, $this->_userId, $user_nick, $file_version[0]["meta_value"]); $file_meta->is_add = false; } else { $meta_value = MUtils::getFileVersions($this->_user_device_name, $query_db_file[0]['file_size'], $file_meta->version_id, MConst::CREATE_FILE, $this->_userId, $user_nick); $file_meta->is_add = true; } $file_meta->meta_value = $meta_value; $file_meta->file_path = $to_path; $create_array[$to_path] = $file_meta; // // 添加到需要更新的版本ref // array_push($this->versions, $file_meta->version_id); } if ($file['file_type'] == 2 || $file['file_type'] == 4) { MiniUserPrivilege::getInstance()->updateByPath($from_path, $to_path); MiniGroupPrivilege::getInstance()->updateByPath($from_path, $to_path); if ($to_parent['dirname'] != $from_parent['dirname']) { MiniUserPrivilege::getInstance()->deleteByFilePath($to_path); MiniGroupPrivilege::getInstance()->deleteByFilePath($to_path); } } // // 创建版本信息 // $ret = MFileMetas::batchCreateFileMetas($create_array, MConst::VERSION); // if ($ret === false) // { // throw new MFileopsException( // Yii::t('api','Internal Server Error'), // MConst::HTTP_CODE_500); // } // // 更新版本 // foreach ($create_array as $file_meta) { if ($file_meta->is_add === true) { // 不存在记录,不需要更新 continue; } MFileMetas::updateFileMeta($file_meta->file_path, MConst::VERSION, $file_meta->meta_value); } // // 更新版本引用次数 // foreach ($this->versions as $vid) { MiniVersion::getInstance()->updateRefCount($vid); } // // 更新该对象元数据 // $file_detail->event_uuid = MiniUtil::getEventRandomString(MConst::LEN_EVENT_UUID); $ret_value = MFiles::updateMoveFileDetail($file_detail); // 移动目录 or 文件 if ($ret_value === false) { throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_500); } $updates = array(); if ($file['file_type'] == 2 || $file['file_type'] == 4) { if ($to_parent['dirname'] != $from_parent['dirname']) { $updates['file_type'] = 1; $updates['user_id'] = $this->_userId; } } if ($fromUserId != $toUserId) { $updates['user_id'] = $toUserId; } MiniFile::getInstance()->updateByPath($to_path, $updates); //被共享者更改文件名更新file_meta记录 MiniFileMeta::getInstance()->modifyFilePath($from_path, 'create_id', $to_path, $file['file_type']); // // 保存移动事件 // by Kindac; // $event_action = $this->getGroupMove($file_detail->from_path, $file_detail->file_path); $ret_value = MiniEvent::getInstance()->createEvent($this->_userId, $user_device_id, $event_action, $file_detail->from_path, $file_detail->file_path, $file_detail->event_uuid, $this->to_share_filter->type); if ($ret_value === false) { throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_500); } if ($file['type'] != 0) { $eventAction = MConst::CREATE_DIRECTORY; } else { $eventAction = MConst::CREATE_FILE; } if ($to_parent['dirname'] == $from_parent['dirname']) { $this->to_share_filter->handlerAction($event_action, $user_device_id, $file_detail->from_path, $file_detail->file_path); } else { if ($this->to_share_filter->is_shared) { $this->to_share_filter->handlerAction($eventAction, $user_device_id, $file_detail->file_path, $file_detail->file_path); } if ($this->from_share_filter->is_shared) { $this->from_share_filter->handlerAction(MConst::DELETE, $user_device_id, $file_detail->from_path, $file_detail->from_path); } } $query_db_file[0]["file_path"] = $file_detail->file_path; $query_db_file[0]["event_uuid"] = $file_detail->event_uuid; if (!empty($deleted)) { MFiles::updateParentId($deleted, $file_detail->id); } //进行扩展操作 $this->extend($from_path, $to_path); //执行完删除操作后执行的额外事物 $after = new MMoveAfter(); $after->action = self::$scene; // $after->from_share_filter = $from_share_filter; $after->to_share_filter = $this->to_share_filter; $after->from_path = $from_path; $after->to_path = $to_path; $after->file_detail = $file_detail; $after->execute(); $this->buildResult($query_db_file[0], $to_path); }
/** * 推送任务到文件冗余备份服务器 * @param $miniHost * @param $task */ private function pushReplicateTask($miniHost, $task) { $node = PluginMiniStoreNode::getInstance()->getNodeById($task->node_id); //如目标服务器不可用,则不用发送请求 if ($node["status"] == 1) { $signature = $task->file_signature; $version = MiniVersion::getInstance()->getBySignature($signature); $downloadUrl = $miniHost . "api.php?route=module/miniStore/download&signature=" . $signature; $callbackUrl = $miniHost . "api.php?route=module/miniStore/replicateReport&signature=" . $signature . "&node_id=" . $node["id"]; //向迷你存储发送冗余备份请求 $data = array('route' => "file/replicate", 'size' => $version["file_size"], 'signature' => $signature, 'download_url' => $downloadUrl, "callback_url" => $callbackUrl); $http = new HttpClient(); $http->post($node["host"] . "/api.php", $data); $content = $http->get_body(); if (!empty($content)) { $status = @json_decode($content)->{"status"}; if ($status == 1) { //目标服务器接受请求后,更改任务状态 $task->status = 1; $task->save(); } } } }
/** * 删除回收站所有记录, 但保留源数据 * @since 1.0.0 * by Kindac */ private function handleSuperClean() { $this->fromIds = $this->getTrashList(); if (empty($this->fromIds)) { $this->handleResult(TRUE, 0, Yii::t('api_message', 'action_success')); Yii::app()->end(); } $files = UserFile::model()->getFilesByIds($this->fromIds, 1); // $files = UserFile::model()->findAllByAttributes(array("user_id" => $this->_userId, "is_deleted" => 1)); $ids = array(); foreach ($files as $file) { array_push($ids, $file["id"]); // // 将文件的版本引用次数减1 // if ($file['file_type'] == 0) { MiniVersion::getInstance()->updateRefCount($file['version_id'], FALSE); } } $ids = join(",", $ids); // 我的最爱和分享都删除 $value = 0; if (!empty($ids)) { FileStar::model()->deleteAll('id in (' . $ids . ')'); MiniLink::getInstance()->unlink($ids); $value = UserFile::model()->updateAll(array("is_deleted" => -1), "id in ({$ids})"); } if ($value >= 0) { $this->handleResult(TRUE, 0, Yii::t('api_message', 'action_success')); } }
/** * 处理非根目录下文件查询 * @param $path * @param $includeDeleted * @return array * @throws MFileopsException */ private function handleNotRootPath($path, $includeDeleted) { // 查询其是否存在信息 $currentFile = MiniFile::getInstance()->getByPath($path); if (empty($currentFile)) { throw new MFileopsException(Yii::t('api', 'not existed'), MConst::HTTP_CODE_404); } //查询文件类型 $version = MiniVersion::getInstance()->getVersion($currentFile["version_id"]); $mimeType = null; if ($version != NULL) { $currentFile["signature"] = $version["file_signature"]; $mimeType = $version["mime_type"]; } $response = array(); $shareKeyPrivilege = MiniFile::getInstance()->getFileExtendProperty($currentFile); $response['share_key'] = $shareKeyPrivilege['share_key']; $response = $this->assembleResponse($response, $currentFile, $mimeType); // 组装子文件数据 $childrenFiles = MiniFile::getInstance()->getChildrenByFileID($parentFileId = $currentFile['id'], $includeDeleted); $contents = array(); if (!empty($childrenFiles)) { foreach ($childrenFiles as $childrenFile) { $childrenFileMeta = MiniFileMeta::getInstance()->getFileMeta($childrenFile['file_path'], 'create_id'); if (!empty($childrenFileMeta)) { $filePathArr = explode('/', $childrenFile['file_path']); $fileOwnerId = $filePathArr[1]; $childrenFileCreateId = $childrenFileMeta['meta_value']; $currentUser = Yii::app()->session["user"]; if ((int) $fileOwnerId !== (int) $currentUser['user_id']) { //当前目录不为当前用户所有(共享目录/公共目录) if ($response['share']['permission'] === '000000000') { continue; } $readPrivilege = substr($response['share']['permission'], 0, 1); if ($readPrivilege === '0') { //如果父目录没有只读权限 if ($childrenFileCreateId != $currentUser['user_id']) { //当没有只读权限时,过滤(用户只能看见共享目录中自己的文件) continue; } } } } $content = array(); $version = MiniVersion::getInstance()->getVersion($childrenFile["version_id"]); $mimeType = null; if ($version != NULL) { $mimeType = $version["mime_type"]; $childrenFile["signature"] = $version["file_signature"]; } $content = $this->assembleResponse($content, $childrenFile, $mimeType); if (!empty($content) && $childrenFile['is_deleted'] == 0) { array_push($contents, $content); } } } $response['contents'] = $contents; return $response; }
/** * 将文件拷贝到临时目录 * @param $zip * @param $file * @param $storePath */ private function addToFile($zip, $file, $storePath) { $fileVersion = MiniVersion::getInstance()->getVersion($file["version_id"]); $content = MiniFile::getInstance()->getFileContentBySignature($fileVersion["file_signature"]); $zip->addFromString($storePath, $content); }
/** * 获取使用空间百分比 * @return number */ public function getUsedPercent() { $remain = $this->getDiskFreeSpace(); //空闲空间 $total = $this->getDiskTotalSpace(); //总空间 $usedSpace = MiniVersion::getInstance()->getTotalSize(); $percent = 0; if ($total > 0) { $percent = (double) $usedSpace / $total; } $retval = round($percent, 3) * 100; return $retval; }
/** * 控制器执行主逻辑函数 * * @return mixed $value 返回最终需要执行完的结果 */ public function invoke($uri = null) { // 调用父类初始化函数,注册自定义的异常和错误处理逻辑 parent::init(); $params = $_REQUEST; // 检查参数 if (isset($params) === false || $params == null) { throw new Exception(Yii::t('api', 'Invalid parameters')); } // 文件大小格式化参数 $locale = "bytes"; if (isset($params["locale"])) { $locale = $params["locale"]; } $url = $uri; $url_manager = new MUrlManager(); $this->_root = $url_manager->parseRootFromUrl($uri); $path = $url_manager->parsePathFromUrl($uri); $path = MUtils::convertStandardPath($path); $originalPath = $path; // 检查共享 $share_filter = MSharesFilter::init(); // $share_filter // // 获取用户数据,如user_id $user = MUserManager::getInstance()->getCurrentUser(); $device = MUserManager::getInstance()->getCurrentDevice(); $this->_user_id = $user["user_id"]; $user_nick = $user["user_name"]; $user_device_id = $device["device_id"]; $this->_user_device_name = $device["user_device_name"]; $rev = $params["rev"]; $rev = intval($rev); $path = "/{$this->_user_id}{$path}"; // // 该文件是否具有此版本 // $file_meta = MFileMetas::queryFileMeta($path, MConst::VERSION); if ($file_meta == false || empty($file_meta)) { throw new MFileopsException(Yii::t('api', ' Unable to find the revision at that path'), MConst::HTTP_CODE_404); } if (MUtils::isExistReversion($rev, $file_meta[0]["meta_value"]) == false) { throw new MFileopsException(Yii::t('api', ' Unable to find the revision at that path'), MConst::HTTP_CODE_404); } // // 查询版本信息 // $version = MiniVersion::getInstance()->getVersion($rev); if ($version == null) { throw new MFileopsException(Yii::t('api', ' Unable to find the revision at that path'), MConst::HTTP_CODE_404); } $size = $version["file_size"]; $file_hash = $version["file_signature"]; // // 查询文件信息 // $query_db_file = MFiles::queryFilesByPath($path); if ($query_db_file === false || empty($query_db_file)) { throw new MFileopsException(Yii::t('api', 'not existed'), MConst::HTTP_CODE_404); } if ($query_db_file[0]["file_type"] == MConst::OBJECT_TYPE_DIRECTORY) { // 文件夹不需要版本 throw new MFileopsException(Yii::t('api', 'folder not existed version'), MConst::HTTP_CODE_403); } if ($rev !== $query_db_file[0]["version_id"]) { // // 更新文件版本 // $updates = array(); $updates["version_id"] = $rev; $updates["file_update_time"] = time(); $updates["file_size"] = $size; $updates["event_uuid"] = MiniUtil::getEventRandomString(MConst::LEN_EVENT_UUID); $ret = MFiles::updateFileDetailById($query_db_file[0]["id"], $updates); if ($ret === false) { throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_500); } $file_detail = new MFiles(); $file_detail->file_name = $query_db_file[0]["file_name"]; // // 保存事件 // $context = array("hash" => $file_hash, "rev" => (int) $rev, "bytes" => (int) $size); // // 增加修改事件 // $ret = MiniEvent::getInstance()->createEvent($this->_user_id, $user_device_id, MConst::MODIFY_FILE, $path, serialize($context), $updates["event_uuid"]); if ($ret === false) { throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_500); } $this->handleFileMeta($path, $rev, $user_nick, $this->_user_device_name, $query_db_file[0]["file_size"]); } // TODO $mime_type = $version["mime_type"]; $response = array(); $response["size"] = MUtils::getSizeByLocale($locale, $size); $response["is_deleted"] = true; $response["bytes"] = intval($size); $response["thumb_exists"] = MUtils::isExistThumbnail($mime_type, $size); $response["path"] = $originalPath; $response["root"] = $this->_root; $response["is_dir"] = false; $response["mime_type"] = $mime_type; $response["modified"] = MUtils::formatIntTime(time()); $response["rev"] = strval($rev); $response["revision"] = $rev; echo json_encode($response); }
/** * 获取文件以前版本的mtadata * @param null $uri * @throws MException * @throws MFilesException */ public function invoke($uri = null) { parent::init(); // 解析url地址,获取root和path,path必须指向一个文件 $urlManager = new MUrlManager(); $path = $urlManager->parsePathFromUrl($uri); $root = $urlManager->parseRootFromUrl($uri); if ($path == false) { throw new MException(Yii::t('api', MConst::PATH_ERROR), MConst::HTTP_CODE_411); } $path = "/" . $path; // Default is 10. Max is 1,000. $revLimit = 10; if (isset($_REQUEST["rev_limit"]) != false) { $revLimit = $_REQUEST["rev_limit"]; } $revLimit = $revLimit <= 1000 ? $revLimit : 1000; // 文件大小格式化参数 $locale = "bytes"; if (isset($_REQUEST["locale"])) { $locale = $_REQUEST["locale"]; } // callback - // TODO 实现callback $callback = NULL; // 获取用户数据,如user_id $user = MUserManager::getInstance()->getCurrentUser(); $device = MUserManager::getInstance()->getCurrentDevice(); $userId = $user["user_id"]; $userNick = $user["user_name"]; $userDeviceId = $device["device_id"]; // // 查询文件 // $fileDetail = MFiles::queryAllFilesByPath("/" . $userId . $path); if ($fileDetail === false || count($fileDetail) == 0) { throw new MException(Yii::t('api', MConst::NOT_FOUND), MConst::HTTP_CODE_404); } // 判断文件类型,如不是文件则返回错误 if ($fileDetail[0]["file_type"] != 0) { throw new MException(Yii::t('api', "Not Acceptable"), MConst::HTTP_CODE_406); } $fileMeta = MFileMetas::queryFileMeta("/" . $userId . $path, MConst::VERSION); if ($fileMeta == false || empty($fileMeta)) { throw new MFilesException(Yii::t("api", MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } // // 文件版本历史 // $versions = unserialize($fileMeta[0]["meta_value"]); $count = 1; // 计数器 // // 轮询 // $response = array(); foreach ($versions as $k => $v) { $var = array(); $var["rev"] = strval($v["version_id"]); $var["revision"] = (int) $v["version_id"]; $var["bytes"] = 0; $var["size"] = "0 bytes"; $var["thumb_exists"] = false; $var["modified"] = MUtils::formatIntTime(microtime(true) * 10000); $var["mime_type"] = MConst::DEFAULT_FILE_MIME_TYPE; $var["path"] = $path; $var["is_dir"] = false; $var["root"] = $root; if ($v["type"] == MConst::DELETE) { $var["is_deleted"] = true; } // // 文件版本信息 // $fileVersion = MiniVersion::getInstance()->getVersion($v["version_id"]); if ($fileVersion == null) { $var["is_deleted"] = true; } else { $var['hash'] = $fileVersion["file_signature"]; $var["bytes"] = (int) $fileVersion["file_size"]; $var["size"] = MUtils::getSizeByLocale($locale, $fileVersion["file_size"]); $var["thumb_exists"] = $this->isExistThumbnail($fileVersion["file_size"], $fileVersion["mime_type"]); $var["modified"] = MUtils::formatIntTime($fileVersion["updated_at"]); $var["mime_type"] = is_null($fileVersion["mime_type"]) ? $var["mime_type"] : $fileVersion["mime_type"]; } array_push($response, $var); if ($count >= $revLimit) { break; } $count += 1; } echo json_encode($response); }
/** * 系统空间是否还有剩余 */ public static function hasOverSysSpace() { $value = MiniOption::getInstance()->getOptionValue("site_sys_space"); if (isset($value) && $value > 0) { $usedSpace = MiniVersion::getInstance()->getTotalSize(); $overSpace = $value * 1024 * 1024 - $usedSpace; if ($overSpace < 0) { return false; } } return true; }
/** * 控制器执行主逻辑函数 */ public function invoke($uri = null) { // 调用父类初始化函数,注册自定义的异常和错误处理逻辑 parent::init(); $params = $_REQUEST; // 检查参数 if (isset($params) === false || $params == null) { throw new MAuthorizationException(Yii::t('api', 'Invalid parameters')); } $url_manager = new MUrlManager(); $path = MUtils::convertStandardPath($url_manager->parsePathFromUrl($uri)); $root = $url_manager->parseRootFromUrl($uri); // 去掉问号后面参数 if ($pos = strpos($this->_root, '?')) { $this->_root = substr($this->_root, 0, $pos); } if ($pos = strpos($path, '?')) { $path = substr($path, 0, $pos); } // 获取用户数据,如user_id $user = MUserManager::getInstance()->getCurrentUser(); $this->_user_id = $user["user_id"]; $query = ""; if (isset($params["query"])) { $query = $params["query"]; } if ($query === "") { throw new MFileopsException(Yii::t('api', 'bad request 15'), MConst::HTTP_CODE_400); } $file_limit = 10000; if (isset($params["file_limit"])) { $file_limit = $params["file_limit"]; } $include_deleted = false; // 处理删除的同样也需要返回 // if(isset($params["include_deleted"])) { // $include_deleted = $params["include_deleted"]; // if(is_string($include_deleted) === true) { // if(strtolower($include_deleted) === "false") { // $include_deleted = false; // } elseif(strtolower($include_deleted) === "true") { // $include_deleted = true; // } // } // } $this->_locale = "bytes"; if (isset($params["locale"])) { $this->_locale = $params["locale"]; } $callback = null; if (isset($params["callback"])) { $callback = $params["callback"]; } if (empty($path) || "/" . $this->_user_id == $path) { $path = '/' . $this->_user_id; $userFiles = array(); $query_db_file = MFiles::searchFilesByPath($path, $query, $this->_user_id, $include_deleted); foreach ($query_db_file as $db_file) { // if(($db_file['parent_file_id'] == 0) and ($db_file['file_type'] != 4) and ($db_file['file_type'] != 2)){ $userFiles[] = $db_file; // } } $retval = $this->handleSearchRoot($path, $query); $files = array_merge($retval, $userFiles); } else { // $files = array(); $includeDeleted = false; $currentFile = MiniFile::getInstance()->getByPath($path); // if (empty($currentFile)){ // throw new MFileopsException(Yii::t('api','not existed'),MConst::HTTP_CODE_404); // } // //查询文件类型 // $version = MiniVersion::getInstance()->getVersion($currentFile["version_id"]); // $mimeType = null; // if ($version != NULL) // { // $currentFile["signature"] = $version["file_signature"]; // $mimeType = $version["mime_type"]; // } // // 组装子文件数据 $childrenFiles = MiniFile::getInstance()->getChildrenByFileID($parentFileId = $currentFile['id'], $includeDeleted); $currentFileParts = explode('/', $path); $currentFileUserId = $currentFileParts[1]; $files = $childrenFiles; // $query = str_replace("%", "\\%", $query); // $sql = ' file_name like "%' . $query . '%"'; // $sql = ''; // $files = array(); // foreach($childrenFiles as $childrenFile){ // $condition = $sql . 'file_path="' . $childrenFile['file_path'] . '" '; // $file = MFiles::findAll($condition); // $files = array_merge($files,$file); // } // $contents = array(); // if(!empty($childrenFiles)){ // foreach($childrenFiles as $childrenFile){ // $content = array(); // $version = MiniVersion::getInstance()->getVersion($childrenFile["version_id"]); // $mimeType = null; // if ($version != NULL){ // $mimeType = $version["mime_type"]; // $childrenFile["signature"] = $version["file_signature"]; // } // $content = $this->assembleResponse($content, $childrenFile, $mimeType); // if(!empty($content) && $childrenFile['is_deleted'] == 0){ // array_push($contents, $content); // } // } // } // $response['contents'] = $contents; } $result = array(); $query = str_replace("%", "\\%", $query); $sql = ' file_name like "%' . $query . '%"'; foreach ($files as $file) { $condition = $sql . 'and file_path like"' . $file['file_path'] . '%" '; $file = MFiles::findAll($condition); if (empty($file)) { continue; } $result = array_merge($result, $file); } // $path = "/{$this->_user_id}{$path}"; // $path = MUtils::convertStandardPath($path) . "/"; // 查询其 信息 // $operator = $this->_user_id; // // $sharefilter = MSharesFilter::init(); // $sharefilter->handlerCheck($this->_user_id, CUtils::removeUserFromPath($path)); // if($sharefilter->is_shared) { // $operator = $sharefilter->master; // $qpath = '/' . $sharefilter->master . $sharefilter->_path; // $query_db_file = MFiles::searchFilesByPath($qpath, $query, $sharefilter->master, $include_deleted); // // // 判断搜索出来的文件是否有权限访问 // foreach($query_db_file as $index => $file) { // // 列表权限,如果没有列表权限,则不进行显示 // try { // $sharefilter->hasPermissionExecute($file['file_path'], MPrivilege::RESOURCE_READ); // }catch(Exception $e) { // unset($query_db_file[$index]); // continue; // } // } // } else { // $query_db_file = MFiles::searchFilesByPath($path, $query, $this->_user_id, $include_deleted); // } // // 查询根目录 // // $retval = $this->handleSearchRoot($path, $query); // $query_db_file = array_merge($query_db_file, $retval); // if (count($query_db_file) > $file_limit) // { // throw new MFileopsException( // Yii::t('api','Too many file entries to return'), // MConst::HTTP_CODE_406); // } // $keys = array(); $response = array(); $filePaths = array(); if (!empty($result)) { foreach ($result as $file) { if (in_array($file['file_path'], $filePaths)) { continue; } array_push($filePaths, $file['file_path']); $item = array(); $version = MiniVersion::getInstance()->getVersion($file["version_id"]); $mimeType = null; $signature = null; if ($version != NULL) { $mimeType = $version["mime_type"]; $signature = $version["file_signature"]; $file["signature"] = $signature; } $item = $this->assembleResponse($item, $file, $mimeType); if (!empty($item)) { array_push($response, $item); } } } // foreach($query_db_file as $key => $db_file) { // if ($key >= $file_limit) // break; // $file_array = array(); // $mime_type = null; // if($db_file["file_type"] == MConst::OBJECT_TYPE_FILE) { // $version = MiniVersion::getInstance()->getVersion($db_file["version_id"]); // if($version) { // $mime_type = $version["mime_type"]; // } // } // $file_array = $this->assembleResponse($file_array, $db_file, $mime_type); // #这里对数据进行了二次过滤,如果路径是一致的,则过滤掉 // #TODO 这里的冗余数据初步分析是权限导致的,二次重构要去掉这个代码 // $path = $file_array["path"]; // if(!array_key_exists($path, $keys)){ // $keys[$path] = $file_array; // array_push($response, $file_array); // } // } echo json_encode($response); }
/** * create file * @param $userId * @param $file * @param $deviceId * @return array */ public function createFile($userId, $file, $deviceId) { $event = new Event(); $event->user_id = $userId; $event->user_device_id = $deviceId; if ((int) $file["file_type"] === MiniFile::$TYPE_FILE) { $event->action = MiniEvent::$CREATE_FILE; } else { //TODO include public folder/share folder/ $event->action = MiniEvent::$CREATE_FOLDER; } $event->file_path = $file["file_path"]; $context = $file["file_path"]; if ((int) $file["file_type"] === MiniFile::$TYPE_FILE) { //get version $version = MiniVersion::getInstance()->getVersion($file["version_id"]); $versionInfo = array("hash" => $version["file_signature"], "rev" => (int) $version["id"], "bytes" => (int) $file["file_size"], "update_time" => (int) $file["file_update_time"], "create_time" => (int) $file["file_create_time"]); $context = serialize($versionInfo); } $event->context = $context; $event->event_uuid = MiniUtil::getEventRandomString(MConst::LEN_EVENT_UUID); $event->type = MiniEvent::$EVENT_COMMON_TYPE; $event->save(); //update file event_uuid MiniFile::getInstance()->update($file["id"], array("event_uuid" => $event->event_uuid)); }
/** * 获得有效文件下载服务器节点 * 找到min(downloaded_file_count) and status=1的记录分配 * @param string $signature 文件内容hash * @return array */ private function getDownloadNode($signature) { $version = MiniVersion::getInstance()->getBySignature($signature); if (!empty($version)) { $metaKey = "store_id"; $meta = MiniVersionMeta::getInstance()->getMeta($version["id"], $metaKey); if (!empty($meta)) { $value = $meta["meta_value"]; $ids = explode(",", $value); $nodes = $this->getNodeList(); $validNodes = array(); foreach ($nodes as $node) { //先找到当前文件存储的节点 $isValidNode = false; foreach ($ids as $validNodeId) { if ($validNodeId == $node["id"]) { $isValidNode = true; } } if (!$isValidNode) { continue; } //然后判断节点是否有效,并在有效的节点找到下载次数最小的节点 if ($node["status"] == 1) { array_push($validNodes, $node); } } //选出downloaded_file_count最小的个节点 $validNodes = MiniUtil::arraySort($validNodes, "downloaded_file_count", SORT_ASC); $nodes = MiniUtil::getFistArray($validNodes, 1); if (count($nodes) > 0) { $node = $nodes[0]; $urlInfo = parse_url($node["host"]); if ($urlInfo["host"] == "127.0.0.1") { //说明迷你存储在本机,直接把127.0.0.1替换为迷你存储端口 $defaultHost = MiniHttp::getMiniHost(); $miniHostInfo = parse_url($defaultHost); $node['host'] = $miniHostInfo["scheme"] . "://" . $miniHostInfo["host"] . ":" . $urlInfo["port"] . $miniHostInfo["path"]; } return $node; } return null; } } return null; }
/** * 获取系统节约空间 */ public function getSaveSpace() { $saveSpace = MiniFile::getInstance()->getTotalSize() - MiniVersion::getInstance()->getTotalSize(); return $saveSpace; }
/** * * 更新文件版本引用次数 * @since 0.9.6 * @param array $files */ private function updateVerRef($files) { foreach ($files as $file) { if ($file->file_type != 0) { continue; } MiniVersion::getInstance()->updateRefCount($file->version_id); } }
/** * * 检查文件data和 meta是否存在 * @param string $hash 文件sha1 * @param string $fileName 文件名 * @return bool|void */ protected function handleCheckFileVersion($hash, $fileName) { $version = MiniVersion::getInstance()->getBySignature($hash); if (!$this->isNewVersion) { //data源处理对象 if ($version == null) { return $this->handleAssign(); } // 检查文件是否存在 $dataObj = Yii::app()->data; $storePath = MiniUtil::getPathBySplitStr($hash); if ($dataObj->exists($storePath) == false) { return $this->handleAssign(); } $this->version_id = $version['id']; $this->size = $version['file_size']; return true; } else { //返回断点文件信息 $data = array(); if (empty($version)) { $miniStoreInfo = MiniUtil::getPluginMiniStoreData(); if (empty($miniStoreInfo)) { //普通文件上传 $data['success'] = false; $data['url'] = MiniHttp::getMiniHost() . "api.php"; $storePath = MiniUtil::getPathBySplitStr($hash); $filePath = BASE . "upload_block/cache/" . $storePath; if (file_exists($filePath)) { $data['offset'] = filesize($filePath); //如文件大小相同而且Hash值相同,说明流数据文件已经存在,直接生成元数据即可 $size = MiniHttp::getParam("size", ""); if ($data['offset'] == $size) { //生成version记录,为使用老逻辑代码,这里处理得很羞涩 //理想的逻辑是在这里直接返回相关结果 $mimeType = MiniUtil::getMimeType($fileName); $version = MiniVersion::getInstance()->create($hash, $size, $mimeType); $this->version_id = $version['id']; $this->size = $version['file_size']; return true; } } else { $data['offset'] = 0; } echo json_encode($data); exit; } else { //迷你存储与第3方存储秒传接口 apply_filters("file_sec", array("route" => "module/miniStore/report", "sign" => MiniHttp::getParam("sign", ""), "access_token" => MiniHttp::getParam("access_token", ""), "signature" => $hash, "size" => MiniHttp::getParam("size", ""), "path" => MiniHttp::getParam("path", ""))); } } else { //上传文件到其它目录下,支持秒传 $this->version_id = $version['id']; $this->size = $version['file_size']; return true; } } }
/** * 清理全部的缓存,包括多余的file_meta * @param $limit */ public function cleanCache($limit) { //data源处理对象 $dataObj = Yii::app()->data; // 回收站插件: -1保留值 0正常 1删除 $this->handleCleanFileMeta($limit); // 清理ref_count等于0的文件 $versions = MiniVersion::getInstance()->getCleanFiles(100); foreach ($versions as $version) { $files = UserFile::model()->findAll('version_id=?', array($version['id'])); // 如果$file存在此version_id,不删除 if (!empty($files)) { for ($i = 0; $i < count($files); $i++) { MiniVersion::getInstance()->updateRefCount($version["id"]); } continue; } // 如果不存在的话,删除流文件,删除该条version记录 $signature = $version['file_signature']; $signaturePath = MiniUtil::getPathBySplitStr($signature); // 判断文件是否存在 if ($dataObj->exists($signaturePath) === false) { MiniVersion::getInstance()->deleteById($version["id"]); continue; } // 删除文件 $dataObj->delete($signaturePath); //删除空的文件夹 $parts = CUtils::getFoldersBySplitStr($signature); foreach ($parts as $part) { $dataObj->delete($part); } // 删除version记录 MiniVersion::getInstance()->deleteById($version["id"]); } MiniUtil::deleteDir(BASE . 'temp'); }
/** * 创建对象 */ public function create() { // 查询文件信息 $path = MiniUtil::getAbsolutePath($this->user_id, $this->path); $file = MiniFile::getInstance()->getByPath($path); if (empty($file)) { throw new MException(Yii::t('api', MConst::PATH_ERROR), MConst::HTTP_CODE_404); } $fileName = $file["file_name"]; $fileSize = $file["file_size"]; $versionId = $file["version_id"]; // 检查是否支持缩略图 $this->checkExistThumbnail($fileName, $fileSize); // 获取文件版本 $version = MFileVersions::queryFileVersionByID($versionId); if (count($version) == 0) { throw new MException(Yii::t('api', MConst::PATH_ERROR), MConst::HTTP_CODE_404); } // 获取文件存储路径 $isTmp = false; $signature = $_REQUEST["signature"]; if (empty($signature) || $signature === "undefined") { $signature = $version[0]["file_signature"]; } // 缩略图大小 $sizeInfo = self::$sizes[$this->size]; if ($sizeInfo === NULL) { $sizeStr = strtolower($this->size); $sizeList = explode("x", $sizeStr); $sizeInfo = array("w" => $sizeList[0], "h" => $sizeList[1]); } $this->width = $sizeInfo["w"]; $this->height = $sizeInfo["h"]; // 检查缩略图是否存在 $thumbnail = THUMBNAIL_TEMP . MiniUtil::getPathBySplitStr($signature); $thumbnail .= "_{$this->width}_{$this->height}.{$this->format}"; if (file_exists($thumbnail) == true) { //直接跳转,避免重复生成缩略图 $url = MiniHttp::getMiniHost() . "assets/thumbnails/" . MiniUtil::getPathBySplitStr($signature); $url .= "_{$this->width}_{$this->height}.{$this->format}"; header('Location: ' . $url); exit; } //判断文件是否在迷你存储中,兼容非迷你存储的文件 $version = MiniVersion::getInstance()->getBySignature($signature); $meta = MiniVersionMeta::getInstance()->getMeta($version["id"], "store_id"); $thumbnailData = array(); if (!empty($meta)) { //为迷你存储缩略图添加hook $thumbnailData["signature"] = $signature; $storePath = apply_filters("image_path", $thumbnailData); } if (empty($storePath) || $storePath === $thumbnailData) { //data源处理对象 $dataObj = Yii::app()->data; $signaturePath = MiniUtil::getPathBySplitStr($signature); if ($dataObj->isExistLocal()) { $storePath = $dataObj->documentStorePath($signaturePath) . $signaturePath; } } if (file_exists($storePath) == false) { throw new MException(Yii::t('api', "The file path was not found."), MConst::HTTP_CODE_404); } $pathInfo = MUtils::pathinfo_utf($fileName); $extension = $pathInfo["extension"]; $tmpPath = DOCUMENT_TEMP . $signature . ".{$extension}"; // 缩略图对象 $this->handler = NULL; $this->image = $tmpPath; $this->resize = true; // 创建缩略图片父目录 if (file_exists(dirname($thumbnail)) == false) { if (MUtils::MkDirsLocal(dirname($thumbnail)) == false) { throw new MException(Yii::t('api', "The file path was not found."), MConst::HTTP_CODE_404); } } // 临时文件父目录 if (file_exists(dirname($tmpPath)) == false) { if (MUtils::MkDirsLocal(dirname($tmpPath)) == false) { throw new MException(Yii::t('api', "The file path was not found."), MConst::HTTP_CODE_404); } } // 拷贝文件到临时目录 if (file_exists($tmpPath) == false) { if (copy($storePath, $tmpPath) == false) { throw new MException(Yii::t('api', "The file path was not found."), MConst::HTTP_CODE_404); } } // 如果图片格式与后缀不一致,转换为一致的 if ($this->format != strtolower($extension)) { $fm = new Image($tmpPath); $format_path = DOCUMENT_TEMP . $signature . ".{$this->format}"; $fm->save($format_path); // 转换成功删除临时文件 unlink($tmpPath); $this->image = $format_path; } if ($isTmp) { unlink($storePath); } // 初始化图像对象 try { $this->handler = new Image($this->image, isset($this->config) ? $this->config : NULL); } catch (MException $e) { Yii::log("Exception : {$e->getTraceAsString()}"); throw new MException(Yii::t('api', "The image is invalid and cannot be thumbnailed."), MConst::HTTP_CODE_415); } // 生成缩略图 if ($this->resize == true) { $this->handler->resize($this->width, $this->height)->rotate(0)->quality(75)->sharpen(20); $chmod = 0644; $keep_actions = true; try { $this->handler->save($thumbnail, $chmod, $keep_actions); $this->handler->setImageFile($thumbnail); $this->image = $thumbnail; @unlink($format_path); } catch (MException $e) { Yii::trace("Exception : {$e}", "miniyun.api"); throw new MException(Yii::t('api', "The image is invalid and cannot be thumbnailed."), MConst::HTTP_CODE_415); } } }
/** * 历史版本恢复 * @param int $deviceId * @param string $filePath * @param string $signature * @return bool */ public function recover($deviceId, $filePath, $signature) { $version = MiniVersion::getInstance()->getBySignature($signature); $file = $this->getModelByPath($filePath); if ($version["id"] == $file['version_id']) { return true; } $device = MiniUserDevice::getInstance()->getById($deviceId); $userId = $device["user_id"]; $user = MiniUser::getInstance()->getUser($userId); $userNick = $user["nick"]; // events表 相关操作 $userDeviceName = $device["user_device_name"]; $userDeviceId = $device["id"]; $signature = $version['file_signature']; $action = CConst::MODIFY_FILE; $file->file_update_time = time(); $context = array('hash' => $signature, 'rev' => (int) $version["id"], 'bytes' => (int) $version['file_size'], 'update_time' => (int) $file->file_update_time, 'create_time' => (int) $file['file_create_time']); $filePath = $file['file_path']; $eventUuid = MiniUtil::getEventRandomString(CConst::LEN_EVENT_UUID); MiniEvent::getInstance()->createEvent($file['user_id'], $userDeviceId, $action, $filePath, serialize($context), $eventUuid); //create event // files表相关操作 $file->version_id = $version["id"]; $file->event_uuid = $eventUuid; $file->file_size = $version['file_size']; $file->save(); // meta表相关操作 $fileMeta = FileMeta::model()->find('file_path = ?', array($filePath)); $versions = CUtils::getFileVersions($userDeviceName, $version['file_size'], $version["id"], CConst::WEB_RESTORE, $userId, $userNick, $fileMeta['meta_value']); $fileMeta->meta_value = $versions; $fileMeta->save(); //更新版本引用数 MiniVersion::getInstance()->updateRefCountByIds(array($version["id"]), TRUE); return true; }
/** * 创建文件 * @param array $fileDetail * @throws * @return array */ private function createFile($fileDetail) { // // 如果创建文件标志为false,则不执行创建 // if ($this->create_file == false) { return; } // // 是否有标记为删除的对象,可能存在多个 // $conflictFile = MFiles::queryFilesByPath($this->file_path, TRUE); if ($conflictFile != false && empty($conflictFile) == false) { foreach ($conflictFile as $file) { // // 如果非文件类型,删除 // if ($file["file_type"] == MConst::OBJECT_TYPE_FILE) { $fileDetail = MFiles::exchange2Object($file, TRUE); $this->creatFileDeleted($fileDetail); return; } else { // 彻底删除之后再进行创建 $trash = new Trash(); $trash->_userId = $this->user_id; $trash->fromIds = $file['id']; try { $trash->invoke(Trash::DELETE); } catch (Exception $e) { throw new MFileopsException(Yii::t('api', 'Internal Server Error'), MConst::HTTP_CODE_500); } } } } $this->spaceFilter($this->size); // 过滤器,空间大小计算 $fileDetail->file_create_time = $this->file_create_time; $fileDetail->file_update_time = $this->file_update_time; $fileDetail->file_size = $this->size; $fileDetail->file_type = MConst::OBJECT_TYPE_FILE; $fileDetail->parent_file_id = $this->parent_file_id; $fileDetail->version_id = $this->version_id; $fileDetail->file_path = $this->path; $fileDetail->file_name = $this->file_name; $fileDetail->event_uuid = MiniUtil::getEventRandomString(MConst::LEN_EVENT_UUID); $fileDetail->mime_type = $this->type; // // 创建文件时,如果存在老的版本 需要兼容 不能覆盖 // $metaValue = null; $fileMeta = MFileMetas::queryFileMeta($fileDetail->file_path, MConst::VERSION); if ($fileMeta) { $metaValue = $fileMeta[0]['meta_value']; } // // 文件meta属性,版本信息 // $version = MUtils::getFileVersions($this->user_device_name, $fileDetail->file_size, $this->version_id, $this->action, $this->user_id, $this->user_nick, $metaValue); // // 保存文件元数据 // $retVal = MFiles::CreateFileDetail($fileDetail, $this->user_id, $this->user_nick); if ($retVal === false) { throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } // // 保存事件 // $this->context = array("hash" => $this->file_hash, "rev" => (int) $this->version_id, "bytes" => (int) $this->size, "update_time" => (int) $this->file_update_time, "create_time" => (int) $this->file_create_time); $retVal = MiniEvent::getInstance()->createEvent($this->currentUserId, $this->user_device_id, $this->action, $this->file_path, serialize($this->context), $fileDetail->event_uuid, $this->share_filter->type); // 为每个共享用户创建事件 $this->share_filter->handlerAction($this->action, $this->user_device_id, $this->file_path, $this->context); if (isset($fileDetail->event_uuid)) { $this->event_uuid = $fileDetail->event_uuid; } if ($retVal === false) { throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } // 文件版本引用次数更新 if (MiniVersion::getInstance()->updateRefCount($this->version_id) == false) { throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } if ($fileMeta) { $retVal = MFileMetas::updateFileMeta($this->file_path, MConst::VERSION, $version); } else { $retVal = MFileMetas::createFileMeta($this->file_path, MConst::VERSION, $version); $pathArr = explode('/', $this->file_path); $user = Yii::app()->session["user"]; if ((int) $pathArr[1] !== (int) $user['user_id']) { //只有当被共享者在共享目录下创建文件时,才会记录create_id MFileMetas::createFileMeta($this->file_path, 'create_id', $user['user_id']); } } if ($retVal === false) { throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } }