Esempio n. 1
0
 /**
  * 通过signature获得文件内容到内存
  * @param $signature
  * @throws
  * @return mix
  */
 public function getFileContentBySignature($signature)
 {
     //下载文件的hook
     $data = array();
     $data["signature"] = $signature;
     $data["file_name"] = "text.txt";
     $data["mime_type"] = "text/html";
     //对网页的处理分为2种逻辑,-1种是直接显示内容,1种是文件直接下载
     $data["force_download"] = -1;
     $retData = apply_filters("file_download_url", $data);
     if ($retData !== $data && !empty($retData)) {
         //通过迷你存储存储的文件,通过代理方式直接请求文件内容
         $content = apply_filters("file_content", $signature);
     } else {
         $filePath = MiniUtil::getPathBySplitStr($signature);
         $oldPath = $filePath . "/" . $signature;
         //data源处理对象
         $dataObj = Yii::app()->data;
         if ($dataObj->exists($oldPath)) {
             //兼容1.4老数据
             $filePath = $oldPath;
         } else {
             if ($dataObj->exists($filePath) === false) {
                 throw new MFilesException(Yii::t('api', MConst::NOT_FOUND), MConst::HTTP_CODE_404);
             }
         }
         $content = $dataObj->get_contents($filePath);
     }
     return $content;
 }
Esempio n. 2
0
 /**
  * 清理全部的缓存,包括多余的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');
 }
Esempio n. 3
0
 /**
  * 创建对象
  */
 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);
         }
     }
 }
 /**
  *
  * 检查文件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;
         }
     }
 }
Esempio n. 5
0
 /**
  * 
  * 大文件断点多线程上传入口,使用put/post方法,推荐使用put
  * 
  * header:
  *      If-Match         - request header,表示文件hash值
  *      ETag             - response header,表示文件hash值
  *      X-Block-Length   - 表示文件每个分片大小,第一次由客户端上传,若服务器端存在则与服务器端保持一致
  *      X-Description    - response header 文件描述信息:00000000000010   1表示这部分内容已经收到,不用再传
  *      X-Content-Length - 文件总大小
  * 
  */
 public function invoke()
 {
     //data源处理对象
     $dataObj = Yii::app()->data;
     parent::init();
     // 获取header值
     $if_match = @$_SERVER['HTTP_IF_MATCH'];
     $clength = isset($_SERVER['CONTENT_LENGTH']) ? $_SERVER['CONTENT_LENGTH'] : 0;
     $crange = @$_SERVER['HTTP_CONTENT_RANGE'];
     $total_size = @$_SERVER['HTTP_X_CONTENT_LENGTH'];
     $block_size = @$_SERVER['HTTP_X_BLOCK_LENGTH'];
     //
     // 检查空间
     //
     $user = MUserManager::getInstance()->getCurrentUser();
     $space = $user["space"];
     $used_space = $user["usedSpace"];
     $used_space += $total_size;
     if ($used_space > $space) {
         throw new MFilesException(Yii::t('api', "User is over storage quota."), MConst::HTTP_CODE_507);
     }
     //
     // 文件临时存储路径
     //
     $this->cache = DOCUMENT_CACHE . MiniUtil::getPathBySplitStr($if_match);
     $des_path = DOCUMENT_CACHE . MiniUtil::getPathBySplitStr($if_match) . ".des";
     $store_path = MiniUtil::getPathBySplitStr($if_match);
     // 表示文件已经上传ok
     if ($dataObj->exists($store_path)) {
         $this->cache = $store_path;
         return true;
     }
     $this->description = $this->hanleDescription($des_path, $this->cache, $total_size, $block_size, $if_match);
     //
     // 表示查询
     //
     if ($clength == 0 && preg_match("/^bytes \\*\\/([0-9]+)/i", $crange, $match)) {
         if ($this->handleCheckCompleted() == true) {
             // 上传完毕检查hash值
             $this->handleCheck($this->cache, $if_match, $store_path, $des_path);
             $this->cache = $store_path;
             return true;
         }
         $this->handleAssigns();
     }
     //
     // 获取文件上传的位置
     //
     if (!preg_match("/^bytes ([0-9]+)-([0-9]+)/i", $crange, $match)) {
         throw new MFilesException(Yii::t('api', MConst::PARAMS_ERROR), MConst::HTTP_CODE_400);
     }
     $start = $match[1];
     $end = $match[2];
     $index = $start / $block_size;
     //
     // 若对应的文件已经上传则返回
     //
     if ($this->description['blocks'][$index] != '1') {
         $this->handleWriteBytes($this->cache, $start, $clength);
         $this->description['blocks'][$index] = "1";
         file_put_contents($des_path, serialize($this->description));
     }
     //
     // 如果没有全部上传完成,则要求客户端继续上传
     //
     if ($this->handleCheckCompleted() == false) {
         $this->handleAssigns();
     }
     // 上传完毕检查hash值
     $this->handleCheck($this->cache, $if_match, $store_path, $des_path);
     $this->cache = $store_path;
 }
Esempio n. 6
0
 /**
  * 保存文件版本
  * @param $tmpName
  * @param $signature
  * @param $size
  * @param bool $move
  * @throws MFilesException
  */
 public function saveFile($tmpName, $signature, $size, $move = true)
 {
     //data源处理对象
     $dataObj = Yii::app()->data;
     //
     // 文件内容保存路径
     //
     $storePath = MiniUtil::getPathBySplitStr($signature);
     if ($dataObj->exists(dirname($storePath)) === false) {
         MUtils::MkDirs(dirname($storePath));
     }
     $version = MiniVersion::getInstance()->getBySignature($signature);
     if ($version != null) {
         //
         // 文件版本id
         //
         $this->version_id = $version["id"];
         $this->file_hash = $version["file_signature"];
         if ($dataObj->exists($storePath) == false) {
             if ($dataObj->put($tmpName, $storePath, true) == false) {
                 throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500);
             }
         }
         if ($move === true) {
             unlink($tmpName);
         }
         return;
     }
     // 移动临时文件到保存路径中
     if ($move === true) {
         if ($dataObj->put($tmpName, $storePath, true) == false) {
             throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500);
         }
     }
     //
     // 创建version
     //
     $version = MiniVersion::getInstance()->create($signature, $size, $this->type);
     if ($version == null) {
         throw new MFilesException(Yii::t('api', MConst::INTERNAL_SERVER_ERROR), MConst::HTTP_CODE_500);
     }
     //
     // 文件版本id
     //
     $this->version_id = $version["id"];
     $this->file_hash = $version["file_signature"];
 }