QiniusController.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\BlogArticle;
  4. use App\Models\CourseArticle;
  5. use App\Services\FileSystem\QiniuAdapter;
  6. use http\Url;
  7. use Illuminate\Http\Request;
  8. use Illuminate\Support\Facades\Auth;
  9. use Illuminate\Support\Facades\Storage;
  10. use League\Flysystem\Filesystem;
  11. class QiniusController extends Controller
  12. {
  13. // 缓存文件列表
  14. protected $cdnFiles = [];
  15. // 缓存 public 文件夹下的目录
  16. protected $cdnPublicDir = [
  17. 'ext',
  18. 'css',
  19. 'js',
  20. 'fonts',
  21. 'images',
  22. 'svg'
  23. ];
  24. public function __construct()
  25. {
  26. $this->path = public_path();
  27. $this->middleware('auth');
  28. }
  29. /**
  30. * 资源管理入口
  31. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  32. */
  33. public function index()
  34. {
  35. $this->isFounder();
  36. return view('pages.qinius.index');
  37. }
  38. /**
  39. * cdns 静态资源
  40. * @param Request $request
  41. * @return \Illuminate\Http\RedirectResponse
  42. */
  43. public function cdns(Request $request)
  44. {
  45. $this->isFounder();
  46. // 允许的动作
  47. $actions = ['delete', 'create', 'refresh'];
  48. // 动作
  49. $action = $request->action;
  50. // 所有的 key
  51. $keys = [];
  52. $str = '';
  53. switch ($action) {
  54. case 'delete':
  55. $str = '清空静态资源';
  56. break;
  57. case 'create':
  58. $str = '上传静态资源';
  59. break;
  60. case 'refresh':
  61. $str = '刷新预取';
  62. break;
  63. }
  64. dump($str . ' 开始,请不要刷新页面 ...');
  65. if (in_array($action, $actions)) {
  66. // 获取实例
  67. $flysystem = new QiniuAdapter('qiniu_cdns', '');
  68. // 列出所有文件
  69. $images = $flysystem->listContents('css');
  70. if (!empty($images)) {
  71. $images = $images['items'];
  72. }
  73. $keys = array_column($images, 'key');
  74. }
  75. if ($action == 'delete') {
  76. foreach ($keys as $key) {
  77. $flysystem->delete($key);
  78. }
  79. }
  80. if ($action == 'create') {
  81. $files = $this->getPublicPath();
  82. foreach ($files as $file){
  83. // 要上传文件的本地路径
  84. $filePath = $file[0];
  85. // 上传到七牛后保存的文件名
  86. $key = $file[1];
  87. Storage::disk('qiniu_cdns')->write($key, $filePath);
  88. }
  89. }
  90. if ($action == 'refresh') {
  91. foreach ($keys as $index=> $key) {
  92. $keys[$index] = assert_cdns($key);
  93. }
  94. $flysystem->refresh($keys);
  95. }
  96. dump($str . ' 完成,即将跳转 ...');
  97. return redirect('qinius')->with('success', $str . '成功 ~');
  98. }
  99. /**
  100. * images 镜像图片库
  101. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  102. */
  103. public function images()
  104. {
  105. $this->isFounder();
  106. // 获取实例
  107. $flysystem = new QiniuAdapter('qiniu', '');
  108. // 列出所有文件
  109. $images = $flysystem->listContents('css');
  110. if (!empty($images)) {
  111. $images = $images['items'];
  112. }
  113. return view('pages.qinius.images', compact('images'));
  114. }
  115. /**
  116. * 主动提交链接给搜索引擎抓取
  117. */
  118. public function urls(Request $request)
  119. {
  120. // 待推送的 url 数组
  121. $urls = [];
  122. $msg = '推送成功 ~';
  123. // 博客文章
  124. $ids = BlogArticle::orderBy('id', 'asc')->pluck('id');
  125. foreach ($ids as $id) {
  126. array_push($urls, route('blog.articles.show', $id));
  127. }
  128. // 教程文章
  129. $ids = CourseArticle::with('section')
  130. ->select('id','course_section_id')
  131. ->orderBy('id', 'asc')
  132. ->get();
  133. // 只有站长可以查看的文章不进行推送
  134. foreach ($ids as $item) {
  135. if ((int) $item->section->book->prices <= 1000) {
  136. $book_id = $item->section->book->id;
  137. $id = $item->id;
  138. array_push($urls, route('course.articles.show', [$book_id, $id]));
  139. }
  140. }
  141. if ($request->action == 'local') {
  142. // 写入文件
  143. $msg = $this->_writeFile($urls);
  144. }elseif ($request->action == 'baidu') {
  145. // 推送百度
  146. $msg = $this->_baidu($urls);
  147. }
  148. return redirect('qinius')->with('success', $msg);
  149. }
  150. /**
  151. * 获取 public 文件夹需要做 cdn 缓存的文件列表
  152. * @return array
  153. */
  154. protected function getPublicPath()
  155. {
  156. $arr = $this->cdnPublicDir;
  157. foreach ($arr as $item) {
  158. $path = $this->path . '/' . $item;
  159. $this->getPublicFile($path, $item);
  160. }
  161. return $this->cdnFiles;
  162. }
  163. /**
  164. * 递归获取文件名
  165. * [
  166. * 0=> [
  167. * 0 => "/home/vagrant/Code/blog/public/css/app.css"
  168. * 1 => "css/app.css"
  169. * ],
  170. * ]
  171. * @param $path
  172. * @param string $key
  173. */
  174. protected function getPublicFile($path, $key='')
  175. {
  176. $dir = opendir($path);
  177. while($filename = readdir($dir)){
  178. if ($filename != '.' && $filename != '..') {
  179. $tmpPath = $path .'/'. $filename;
  180. $tmpKey = $key.'/'.$filename;
  181. if (is_dir($tmpPath)) {
  182. $this->getPublicFile($tmpPath, $tmpKey);
  183. } else {
  184. $this->cdnFiles[] = [
  185. $tmpPath,
  186. $tmpKey
  187. ];
  188. }
  189. }
  190. };
  191. closedir($dir);
  192. }
  193. /**
  194. * 写入文件 uploads/urls.html
  195. * @param array $urls
  196. * @return string
  197. */
  198. protected function _writeFile($urls = [])
  199. {
  200. $file = public_path() . '/uploads/urls.html';
  201. $fp = fopen($file, 'w');
  202. fwrite($fp, '<textarea style="width: 100%;height: 90vh;">' . PHP_EOL);
  203. foreach ($urls as $url) {
  204. fwrite($fp, $url . PHP_EOL);
  205. }
  206. fwrite($fp, '</textarea>' . PHP_EOL);
  207. fclose($fp);
  208. return config('app.url') . '/uploads/urls.html';
  209. }
  210. /**
  211. * 推送到百度
  212. * @param array $urls
  213. * @return \Illuminate\Http\RedirectResponse
  214. */
  215. private function _baidu($urls = [])
  216. {
  217. $msg = '推送成功 ~';
  218. $api = 'http://data.zz.baidu.com/urls?site=https://www.learnku.net&token=pJNUfWjlnSnO1Ss7';
  219. $ch = curl_init();
  220. $options = array(
  221. CURLOPT_URL => $api,
  222. CURLOPT_POST => true,
  223. CURLOPT_RETURNTRANSFER => true,
  224. CURLOPT_POSTFIELDS => implode("\n", $urls),
  225. CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
  226. );
  227. curl_setopt_array($ch, $options);
  228. $result = curl_exec($ch);
  229. $result = json_decode($result);
  230. if (isset($result->error)){
  231. $msg = $result->message;
  232. } elseif ($result->success == '0') {
  233. if (!empty($result->not_same_site)) {
  234. $msg = '由于不是本站url而未处理的url列表' . json_encode($result->not_same_site);
  235. } elseif (!empty($result->not_valid)) {
  236. $msg = '不合法的url列表' . json_encode($result->not_valid);
  237. }
  238. } else {
  239. $msg = $msg . $result->success . '条';
  240. }
  241. return $msg;
  242. }
  243. /**
  244. * 鉴权处理
  245. */
  246. protected function isFounder(){
  247. if (Auth::user() && Auth::user()->hasRole('Founder')) {
  248. // ...
  249. } else {
  250. abort(403);
  251. }
  252. }
  253. }