/** * 迷你存储报俊 * @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(); }
/** * (non-PHPdoc) * @see MFilesecController::invoke() */ public function invoke($uri = NULL) { $size = isset($_REQUEST['size']) ? $_REQUEST['size'] : NULL; if ($size === NULL || $size < 0) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR . 'Missing parameter'), MConst::HTTP_CODE_400); } $hash = $_REQUEST["hash"]; $this->size = $size; $url_manager = new MUrlManager(); $path = $url_manager->parsePathFromUrl($uri); $path_info = MUtils::pathinfo_utf($path); $file_name = $path_info["basename"]; $this->type = MiniUtil::getMimeType($file_name); //如果文件的block存在则直接创建meta,表示创建成功否则返回上传文件的参数 if ($this->handleCheckFileVersionSearch($hash)) { parent::invoke($uri); } else { //空间检查 $this->spaceFilter($size); echo json_encode(array("hash" => $hash, "filename" => $file_name)); } }
/** * * 文件上传成功后,向迷你文档服务器发送文档转换请求 * @param $data 文件sha1编码 * @return bool */ function fileUploadAfter($data) { $signature = $data["signature"]; $fileName = $data["file_name"]; $newMimeType = MiniUtil::getMimeType($fileName); $mimeTypeList = array("text/plain", "text/html", "application/javascript", "text/css", "application/xml"); foreach ($mimeTypeList as $mimeType) { if ($mimeType === $newMimeType) { //文本类文件直接把内容存储到数据库中,便于全文检索 do_action("pull_text_search", $signature); return; } } $mimeTypeList = array("application/mspowerpoint", "application/msword", "application/msexcel", "application/pdf"); foreach ($mimeTypeList as $mimeType) { if ($mimeType === $newMimeType) { //文档类增量转换 PluginMiniDocVersion::getInstance()->pushConvertSignature($signature, $newMimeType); break; } } return true; }
/** * 更名 */ public function updateFileName($id, $name, &$message) { if (CUtils::checkNameInvalid($name) || strstr($name, '&') || strstr($name, ';')) { $message = Yii::t("front_common", "name_error"); return false; } $model = $this->findByAttributes(array('id' => $id)); if (empty($model)) { $message = Yii::t("admin_common", "rename_file_not_found"); return false; } $oldPath = $model['file_path']; $model['file_name'] = $name; $model['file_path'] = dirname($model['file_path']) . "/" . $name; // // 判断同名否 // $same = $this->findByAttributes(array('file_path' => $model['file_path'])); if ($same) { $message = Yii::t("admin_common", "rename_file_already_exists"); return false; } $time = (int) time(); $model['file_update_time'] = $time; $path = $model['file_path']; $context = $path; $device_id = Yii::app()->session["deviceId"]; $share_filter = MSharesFilter::init(); $share_filter->handlerCheckByFile($model['user_id'], $model); if ($model['file_type'] == 0) { $model['mime_type'] = MiniUtil::getMimeType($name); // // 如果是文件,需要创建版本 // $user = Yii::app()->session['user']; $device = UserDevice::model()->findByUserIdAndType($user['id'], CConst::DEVICE_WEB); $deviceName = $device["user_device_name"]; $this->_saveFileMeta($path, $model['version_id'], $user['id'], $user['name'], CConst::CREATE_FILE, $deviceName, $model['file_size']); } else { // // 文件夹需要更名所有子目录 // $moreFile = UserFile::model()->findAll("file_path like :type", array('type' => $oldPath . '%')); foreach ($moreFile as $key => $value) { $data = date("Y-m-d H:i:s", time()); // // 查找匹配路径 index, 替换路径 // $index = strlen($oldPath); $value['file_path'] = substr_replace($value['file_path'], $model['file_path'], 0, $index); $s = UserFile::model()->updateAll(array('file_path' => $value['file_path'], 'file_update_time' => $time, 'updated_at' => $data), "id=" . $value['id']); // 文件创建meta if ($value['file_type'] == 0) { // // 如果是文件,需要创建版本 // $user = Yii::app()->session['user']; $device = UserDevice::model()->findByUserIdAndType($user['id'], CConst::DEVICE_WEB); $deviceName = $device["user_device_name"]; $this->_saveFileMeta($value['file_path'], $value['version_id'], $user['id'], $user['name'], CConst::CREATE_FILE, $deviceName, $value['file_size']); } } } $user_id = $model['user_id']; $event_uuid = MiniUtil::getEventRandomString(46); $action = MConst::MOVE; // 重命名 MiniEvent::getInstance()->createEvent($user_id, $device_id, $action, $oldPath, $context, $event_uuid, $share_filter->type); // // 重命名共享目录 // if ($model['file_type'] >= 2) { $share_filter->handlerRenameShared($oldPath, $context); } else { $share_filter->handlerAction($action, $device_id, $oldPath, $context); } $model['event_uuid'] = $event_uuid; $message = Yii::t("admin_common", "rename_file_success"); return $model->save(false); }
/** * 控制器执行主逻辑函数 */ public function invoke($uri = null) { $this->setAction(MConst::CREATE_FILE); // 调用父类初始化函数,注册自定义的异常和错误处理逻辑 parent::init(); $urlManager = new MUrlManager(); $root = $urlManager->parseRootFromUrl($uri); if ($root == false) { //支持参数模式传递上传路径 $path = MiniHttp::getParam("path", ""); if (empty($path)) { throw new MFilesException(Yii::t('api', MConst::PATH_ERROR), MConst::HTTP_CODE_411); } } // 初始化创建文件公共类句柄 $createFileHandler = MFilesCommon::initMFilesCommon(); if (count($_FILES) == 0) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR . "5"), MConst::HTTP_CODE_400); } $keys = array_keys($_FILES); if (count($keys) != 1) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR . "6"), MConst::HTTP_CODE_400); } $key = $keys[0]; // 检查请求参数$_FILES if (isset($_FILES[$key]) === false) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR . "7"), MConst::HTTP_CODE_400); } // 检查文件上传过程是否有错 if ($_FILES[$key]["error"] != 0) { throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR . "8"), MConst::HTTP_CODE_400); } $fileName = $_FILES[$key]["name"]; $type = MiniUtil::getMimeType($fileName); $size = $_FILES[$key]["size"]; $tmpName = $_FILES[$key]["tmp_name"]; // 验证文件是否已经上传成功 if (file_exists($tmpName) === false) { throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500); } // 检查文件上传错误 if (filesize($tmpName) != $size) { throw new MFilesException(Yii::t('api', "The file upload error!"), MConst::HTTP_CODE_400); } //断点文件上传 if ($this->isBreakpointUpload()) { $filesController = new MFilePutController(); $filesController->invoke($uri); } else { //完整文件上传 $signature = MiniUtil::getFileHash($tmpName); // 解析路径 $path = MiniHttp::getParam("path", ""); $path = MiniUtil::specialWordReplace($path); $parentPath = dirname($path); $user = MUserManager::getInstance()->getCurrentUser(); $parentFile = MiniFile::getInstance()->getByPath($parentPath); //如果目录存在,且该目录is_delete=1,则把目录状态删除状态修改为0 if (!empty($parentFile) && $parentFile['is_deleted'] == 1) { $values = array(); $values['is_deleted'] = false; MiniFile::getInstance()->updateByPath($parentPath, $values); } else { //如果是根目录,则不用新建目录 //否则会创建文件名名称的文件夹出来,而且目标文件位于该文件夹的下面 if (!MiniUtil::isRootPath($parentPath, $user["id"])) { MiniFile::getInstance()->createFolder($parentPath, $user['id']); } } $createFileHandler->size = $size; $createFileHandler->parent_path = MUtils::convertStandardPath($parentPath); $createFileHandler->file_name = MiniUtil::specialWordReplace($fileName); $createFileHandler->root = $root; $createFileHandler->path = MUtils::convertStandardPath($path); $createFileHandler->type = $type; // 文件不存在,保存文件 $createFileHandler->saveFile($tmpName, $signature, $size); // 保存文件meta $createFileHandler->saveFileMeta(); // 处理不同端,不同返回值 if (MUserManager::getInstance()->isWeb() === true) { $createFileHandler->buildWebResponse(); return; } $createFileHandler->buildResult(); } }
/** * 处理返回值 */ public function buildResult($query_db_file, $to_path = null) { // 处理不同端,不同返回值 if (MUserManager::getInstance()->isWeb() === true) { $this->buildWebResponse(); return; } if ($this->isEcho === false) { return; } $is_dir = true; $size = $query_db_file["file_size"]; $response = array(); if ($query_db_file["file_type"] == MConst::OBJECT_TYPE_FILE) { // 根据文件名后缀判断mime type $mime_type = MiniUtil::getMimeType($query_db_file["file_name"]); $is_dir = false; $response["mime_type"] = $mime_type; $response["thumb_exists"] = MUtils::isExistThumbnail($mime_type, (int) $query_db_file["file_size"]); } // 去除/{user_id} $path = CUtils::removeUserFromPath($query_db_file["file_path"]); $response["size"] = MUtils::getSizeByLocale($this->_locale, $size); $response["is_deleted"] = false; $response["bytes"] = intval($size); $response["modified"] = MUtils::formatIntTime($query_db_file["file_update_time"]); if ($to_path) { $path = $to_path; } else { $path = $query_db_file["file_path"]; } $path_info = MUtils::pathinfo_utf($path); $path_info_out = MUtils::pathinfo_utf($this->to_share_filter->src_path); $path = MUtils::convertStandardPath($path_info_out['dirname'] . "/" . $path_info['basename']); $response["path"] = $path; $response["root"] = $this->_root; $response["is_dir"] = $is_dir; $response["rev"] = strval($query_db_file["version_id"]); $response["revision"] = intval($query_db_file["version_id"]); // 增加操作返回事件编码 $response["event_uuid"] = $query_db_file["event_uuid"]; echo json_encode($response); }
/** * 处理组装复制文件需要的对象 * @param $fileName * @param $parentFileId * @param $fileDetail * @param $queryDbFile */ public function assembleFileDetail($fileName, $parentFileId, $fileDetail, $queryDbFile) { $filePath = $queryDbFile["file_path"]; $fileDetail->file_type = $queryDbFile["file_type"]; $eventAction = MConst::CREATE_DIRECTORY; $fileDetail->context = $filePath; $fileDetail->mime_type = NULL; if ($fileDetail->file_type == MConst::OBJECT_TYPE_FILE) { $fileDetail->mime_type = MiniUtil::getMimeType($fileName); $eventAction = MConst::CREATE_FILE; $versionId = $queryDbFile["version_id"]; $version = MiniVersion::getInstance()->getVersion($versionId); if ($version != null) { $context = array("hash" => $version["file_signature"], "rev" => (int) $versionId, "bytes" => (int) $queryDbFile["file_size"], "update_time" => (int) $queryDbFile["file_update_time"], "create_time" => (int) $queryDbFile["file_create_time"]); $fileDetail->context = serialize($context); } } elseif ($fileDetail->file_type > MConst::OBJECT_TYPE_DIRECTORY) { $fileDetail->file_type = 1; } $fileDetail->from_id = $queryDbFile['id']; $fileDetail->parent_file_id = $parentFileId; $fileDetail->event_action = $eventAction; $fileDetail->file_name = $fileName; $fileDetail->version_id = $queryDbFile["version_id"]; $fileDetail->file_size = $queryDbFile["file_size"]; $fileDetail->event_uuid = MiniUtil::getEventRandomString(MConst::LEN_EVENT_UUID); $index = strlen($this->_from_path); $filePath = substr_replace($filePath, $this->_to_path, 0, $index); $fileDetail->from_path = $filePath; $fileDetail->file_path = $filePath; $fileDetail->file_create_time = time(); $fileDetail->file_update_time = time(); }
/** * 处理组装请求元数据 * */ private function assembleResponse($response, $file, $mimeType) { $filePath = $file["file_path"]; $response["size"] = MUtils::getSizeByLocale($this->_locale, $file["file_size"]); $response["bytes"] = (int) $file["file_size"]; $response["path"] = $filePath; $response["modified"] = MUtils::formatIntTime($file["file_update_time"]); $response["create_time"] = $file["file_create_time"]; $response["update_time"] = $file["file_update_time"]; $response["revision"] = intval($file["version_id"]); $response["rev"] = strval($file["version_id"]); $response["root"] = $this->_root; $response["hash"] = !empty($file["signature"]) ? $file["signature"] : ""; $response["event"] = $file["event_uuid"]; $response["sort"] = (int) $file["sort"]; //外链Key $response["share_key"] = $file["share_key"]; $response['is_dir'] = false; $permission = UserPermissionBiz::getInstance()->getPermission($filePath, $this->_user_id); if (!empty($permission)) { if (isset($permission['children_shared'])) { $response['children_shared'] = true; } else { $response['share'] = $permission; } if (empty($permission['permission'])) { //如果没有$permission['permission']权限 则直接返回null return null; } } if ($file["file_type"] == MConst::OBJECT_TYPE_FILE) { $response["hash"] = $file["signature"]; $mimeType = MiniUtil::getMimeType($file['file_path']); $response["thumb_exists"] = MUtils::isExistThumbnail($mimeType, (int) $file["file_size"]); } else { $response['is_dir'] = true; } if ($file["file_type"] > MConst::OBJECT_TYPE_FILE) { $response["type"] = (int) $file["file_type"]; } if (!empty($mimeType)) { $response["mime_type"] = $mimeType; } if ($file["is_deleted"] == true) { $response["is_deleted"] = true; } return $response; }
/** * 处理组装请求元数据 * @param $response * @param $file * @param $mimeType * @return mixed */ private function assembleResponse($response, $file, $mimeType) { $filePath = $file["file_path"]; $result = LockBiz::getInstance()->status($filePath); $response['lock'] = $result["success"]; $response["size"] = MUtils::getSizeByLocale($this->locale, $file["file_size"]); $response["bytes"] = (int) $file["file_size"]; $response["path"] = $filePath; $response["file_name_pinyin"] = $file['file_name_pinyin']; $response["modified"] = MUtils::formatIntTime($file["file_update_time"]); $response["create_time"] = $file["file_create_time"]; $response["update_time"] = $file["file_update_time"]; $response["revision"] = intval($file["version_id"]); $response["rev"] = strval($file["version_id"]); $response["root"] = $this->root; $response["hash"] = !empty($file["signature"]) ? $file["signature"] : ""; $response["event"] = $file["event_uuid"]; $response["sort"] = (int) $file["sort"]; //外链Key $link = MiniLink::getInstance()->getByFileId($file['id']); if (empty($link['share_key'])) { $response["share_key"] = ''; } else { $response["share_key"] = $link['share_key']; } $response['is_dir'] = false; $permission = UserPermissionBiz::getInstance()->getPermission($filePath, $this->userId); if (!empty($permission)) { if (isset($permission['children_shared'])) { $response['children_shared'] = true; } else { $permission["share_model"] = $this->getShareModel($filePath); $response['share'] = $permission; } $filePermission = new MiniPermission($permission['permission']); $response['canDelete'] = $filePermission->canDeleteFile(); if (empty($permission['permission'])) { return null; } } if ($file["file_type"] == MConst::OBJECT_TYPE_FILE) { $mimeType = MiniUtil::getMimeType($file['file_path']); $response["thumb_exists"] = MUtils::isExistThumbnail($mimeType, (int) $file["file_size"]); } else { $response['is_dir'] = true; } if ($file["file_type"] > MConst::OBJECT_TYPE_FILE) { $response["type"] = (int) $file["file_type"]; } if (!empty($mimeType)) { $response["mime_type"] = $mimeType; } if ($file["is_deleted"] == true) { $response["is_deleted"] = true; } return $response; }
/** * * 检查文件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; } } }