FileUrl.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. /**
  3. * 文件地址
  4. * @author solu
  5. */
  6. use Aws\S3\S3Client;
  7. class FileUrl extends Model {
  8. protected $tableName = 'file_url';
  9. protected $dbKey = 'dw_chat';
  10. const TMP_DIR = '/tmp/mee/';
  11. const TYPE_OTHER = 0; // 其他
  12. const TYPE_IMAGE = 1; // 图片
  13. const TYPE_VIDEO = 2; // 视频
  14. const TYPE_AUDIO = 3; // 音频
  15. private static $arrType = [
  16. self::TYPE_OTHER => '其他',
  17. self::TYPE_IMAGE => '图片',
  18. self::TYPE_VIDEO => '视频',
  19. self::TYPE_AUDIO => '音频',
  20. ];
  21. public static function getAllType() {
  22. return self::$arrType;
  23. }
  24. /**
  25. * @param $tmpPath
  26. * @param $filename
  27. * @param $mimeType
  28. * @param $forever
  29. * @return mixed|null
  30. * @throws Exception
  31. */
  32. public function getFileUrl($tmpPath, $filename, $mimeType, $forever = false) {
  33. // 控制频率
  34. $objLock = new Lock('file_upload', 300, 50);
  35. $uid = User::getUserId();
  36. $objLock->lock($uid);
  37. if (!file_exists($tmpPath)) {
  38. throw new Exception('file not exists', CODE_PARAM_ERROR);
  39. }
  40. $md5 = md5_file($tmpPath);
  41. $row = $this->objTable->getRow(['id' => $md5]);
  42. if ($row['forever'] || (strtotime($row['update_time'])+20*86400 > time())) {
  43. return $row['url'];
  44. }
  45. $ext = pathinfo($filename, PATHINFO_EXTENSION);
  46. $type = self::getType($mimeType);
  47. $filename = self::getFileName($md5, $tmpPath, $type, $ext);
  48. $url = self::s3PutObject($tmpPath, $filename, $mimeType, $forever);
  49. if ($url) {
  50. $this->objTable->replaceObject([
  51. 'id' => $md5,
  52. 'url' => $url,
  53. 'type' => $type,
  54. 'update_time' => date('Y-m-d H:i:s'),
  55. 'forever' => $forever ? 1 : 0,
  56. ]);
  57. }
  58. $objLock->unlock($uid);
  59. return $url;
  60. }
  61. private static function getFileName($md5, $path, $type, $ext = '') {
  62. if ($type == self::TYPE_IMAGE) {
  63. if (!class_exists('Imagick')) {
  64. $len = filesize($path);
  65. $arr = getimagesize($path);
  66. $str = sprintf('%s_%s_%s', $md5, "size{$arr[0]}x{$arr[1]}", "len{$len}");
  67. } else {
  68. list($color, $width, $height, $len) = self::getImageMainColor($path);
  69. $str = sprintf('%s_%s_%s_%s', $md5, "size{$width}x{$height}", "len{$len}", $color);
  70. }
  71. } else {
  72. $len = filesize($path);
  73. $str = sprintf('%s_%s', $md5, "len{$len}");
  74. }
  75. $ext && $str .= ".{$ext}";
  76. return $str;
  77. }
  78. /**
  79. * 获取类型
  80. * @author solu
  81. * @param $mineType
  82. * @return int
  83. */
  84. public static function getType($mineType) {
  85. if (false !== strpos($mineType, 'image')) {
  86. return self::TYPE_IMAGE;
  87. } elseif (false !== strpos($mineType, 'video')) {
  88. return self::TYPE_VIDEO;
  89. } elseif (false !== strpos($mineType, 'audio')) {
  90. return self::TYPE_AUDIO;
  91. }
  92. return self::TYPE_OTHER;
  93. }
  94. /**
  95. * 上传文件
  96. * @author solu
  97. * @param $path
  98. * @param $name
  99. * @param $mime
  100. * @param $forever
  101. * @return string
  102. * @throws Exception
  103. */
  104. private static function s3PutObject($path, $name, $mime, $forever = false) {
  105. $s3 = new S3Client([
  106. 'version' => 'latest',
  107. 'region' => 'ap-northeast-1',
  108. 'scheme' => 'http',
  109. 'credentials' => [
  110. 'key' => AWS_ACCESS_KEY,
  111. 'secret' => AWS_SECRET_KEY,
  112. ],
  113. ]);
  114. $bucket = $forever ? BUCKET_MEE : BUCKET_MEE_TMP;
  115. $option = [
  116. 'Bucket' => $bucket,
  117. 'Key' => $name,
  118. 'CacheControl' => 'max-age=8640000', // 前端缓存100天
  119. 'Body' => fopen($path, 'r'),
  120. 'ACL' => 'public-read',
  121. 'ContentType' => $mime,
  122. ];
  123. $result = $s3->putObject($option);
  124. $url = $result->get('ObjectURL');
  125. if (!$url) {
  126. throw new Exception('upload to s3 error', CODE_NORMAL_ERROR);
  127. }
  128. return self::_fixUrl($url, $forever);
  129. }
  130. /**
  131. * 转换url
  132. * @author solu
  133. * @param $url
  134. * @param $forever
  135. * @return string
  136. */
  137. private static function _fixUrl($url, $forever = false) {
  138. $cdn = $forever ? CDN_HOST : CDN_HOST_TMP;
  139. if (strpos($url, $cdn) === false) {
  140. $pos = strrpos($url, '/') + 1;
  141. $path = substr($url, $pos);
  142. return sprintf('https://%s/%s', $cdn, $path);
  143. }
  144. return $url;
  145. }
  146. /**
  147. * 视频封面图
  148. * @author solu
  149. * @param $filePath
  150. * @param $filename
  151. * @return mixed|null
  152. * @throws Exception
  153. */
  154. public function getVideoCover($filePath, $filename) {
  155. $info = pathinfo($filename);
  156. $imageName = $info['filename'] . '.jpg';
  157. $imagePath = self::TMP_DIR . $imageName;
  158. if (!file_exists(self::TMP_DIR)) {
  159. mkdir(self::TMP_DIR, 0777, true);
  160. }
  161. exec("ffmpeg -ss 00:00:00 -i '{$filePath}' -y -f image2 -vframes 1 {$imagePath} 1>/dev/null 2>/dev/null");
  162. if(!filesize($imagePath)) {
  163. return null;
  164. }
  165. $url = $this->getFileUrl($imagePath, $imageName, 'image/jpeg');
  166. unlink($imagePath);
  167. return $url;
  168. }
  169. /**
  170. * 获取图片主色调
  171. * @author solu
  172. * @param $path
  173. * @return array
  174. */
  175. public static function getImageMainColor($path) {
  176. $color = '';
  177. $width = 0;
  178. $height = 0;
  179. $len = 0;
  180. if (!class_exists('Imagick')) {
  181. return [];
  182. }
  183. try {
  184. $image = new \Imagick($path); //$file 图片存储地址或者url地址
  185. $width = $image->getImageWidth();
  186. $height = $image->getImageHeight();
  187. $len = $image->getImageLength();
  188. $image->quantizeImage(1, \Imagick::COLORSPACE_RGB, 0, false, false); //获取到只剩1个颜色值, 也可以多取几个
  189. $image->uniqueImageColors();
  190. $iter = $image->getPixelIterator();
  191. $iter->resetIterator();
  192. $row = $iter->getNextIteratorRow();
  193. $row = $row[0];
  194. $arrColor = $row->getColor();
  195. $color = sprintf("%02x%02x%02x", $arrColor['r'], $arrColor['g'], $arrColor['b']);
  196. } catch (Exception $e) {}
  197. return [$color, $width, $height, $len];
  198. }
  199. }