'其他', self::TYPE_IMAGE => '图片', self::TYPE_VIDEO => '视频', self::TYPE_AUDIO => '音频', ]; public static function getAllType() { return self::$arrType; } /** * @param $tmpPath * @param $filename * @param $mimeType * @param $forever * @return mixed|null * @throws Exception */ public function getFileUrl($tmpPath, $filename, $mimeType, $forever = false) { // 控制频率 $objLock = new Lock('file_upload', 300, 50); $uid = User::getUserId(); $objLock->lock($uid); if (!file_exists($tmpPath)) { throw new Exception('file not exists', CODE_PARAM_ERROR); } $md5 = md5_file($tmpPath); $row = $this->objTable->getRow(['id' => $md5]); if ($row['forever'] || (strtotime($row['update_time'])+20*86400 > time())) { return $row['url']; } $ext = pathinfo($filename, PATHINFO_EXTENSION); $type = self::getType($mimeType); $filename = self::getFileName($md5, $tmpPath, $type, $ext); $url = self::s3PutObject($tmpPath, $filename, $mimeType, $forever); if ($url) { $this->objTable->replaceObject([ 'id' => $md5, 'url' => $url, 'type' => $type, 'update_time' => date('Y-m-d H:i:s'), 'forever' => $forever ? 1 : 0, ]); } $objLock->unlock($uid); return $url; } private static function getFileName($md5, $path, $type, $ext = '') { $len = filesize($path); if ($type == self::TYPE_IMAGE) { $arr = getimagesize($path); $str = sprintf('%s_%s_%s', $md5, "size{$arr[0]}x{$arr[1]}", "len{$len}"); } else { $str = sprintf('%s_%s', $md5, "len{$len}"); } $ext && $str .= ".{$ext}"; return $str; } /** * 获取类型 * @author solu * @param $mineType * @return int */ public static function getType($mineType) { if (false !== strpos($mineType, 'image')) { return self::TYPE_IMAGE; } elseif (false !== strpos($mineType, 'video')) { return self::TYPE_VIDEO; } elseif (false !== strpos($mineType, 'audio')) { return self::TYPE_AUDIO; } return self::TYPE_OTHER; } /** * 上传文件 * @author solu * @param $path * @param $name * @param $mime * @param $forever * @return string * @throws Exception */ private static function s3PutObject($path, $name, $mime, $forever = false) { $s3 = new S3Client([ 'version' => 'latest', 'region' => 'ap-northeast-1', 'scheme' => 'http', 'credentials' => [ 'key' => AWS_ACCESS_KEY, 'secret' => AWS_SECRET_KEY, ], ]); $bucket = $forever ? BUCKET_MEE : BUCKET_MEE_TMP; $option = [ 'Bucket' => $bucket, 'Key' => $name, 'CacheControl' => 'max-age=8640000', // 前端缓存100天 'Body' => fopen($path, 'r'), 'ACL' => 'public-read', 'ContentType' => $mime, ]; $result = $s3->putObject($option); $url = $result->get('ObjectURL'); if (!$url) { throw new Exception('upload to s3 error', CODE_NORMAL_ERROR); } return self::_fixUrl($url, $forever); } /** * 转换url * @author solu * @param $url * @param $forever * @return string */ private static function _fixUrl($url, $forever = false) { $cdn = $forever ? CDN_HOST : CDN_HOST_TMP; if (strpos($url, $cdn) === false) { $pos = strrpos($url, '/') + 1; $path = substr($url, $pos); return sprintf('https://%s/%s', $cdn, $path); } return $url; } }