MediaStorageService.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. namespace App\Services;
  3. use App\Util\ActivityPub\Helpers;
  4. use Illuminate\Http\File;
  5. use Illuminate\Support\Facades\Cache;
  6. use Illuminate\Support\Facades\Redis;
  7. use Illuminate\Support\Facades\Storage;
  8. use Illuminate\Support\Str;
  9. use App\Media;
  10. use App\Profile;
  11. use App\User;
  12. use GuzzleHttp\Client;
  13. class MediaStorageService {
  14. public static function store(Media $media)
  15. {
  16. if(config('pixelfed.cloud_storage') == true) {
  17. (new self())->cloudStore($media);
  18. }
  19. return;
  20. }
  21. public static function head($url)
  22. {
  23. $c = new Client();
  24. $r = $c->request('HEAD', $url);
  25. $h = $r->getHeaders();
  26. return [
  27. 'length' => $h['Content-Length'][0],
  28. 'mime' => $h['Content-Type'][0]
  29. ];
  30. }
  31. protected function cloudStore($media)
  32. {
  33. if($media->remote_media == true) {
  34. (new self())->remoteToCloud($media);
  35. } else {
  36. (new self())->localToCloud($media);
  37. }
  38. }
  39. protected function localToCloud($media)
  40. {
  41. $path = storage_path('app/'.$media->media_path);
  42. $thumb = storage_path('app/'.$media->thumbnail_path);
  43. $p = explode('/', $media->media_path);
  44. $name = array_pop($p);
  45. $pt = explode('/', $media->thumbnail_path);
  46. $thumbname = array_pop($pt);
  47. $storagePath = implode('/', $p);
  48. $disk = Storage::disk(config('filesystems.cloud'));
  49. $file = $disk->putFileAs($storagePath, new File($path), $name, 'public');
  50. $url = $disk->url($file);
  51. $thumbFile = $disk->putFileAs($storagePath, new File($thumb), $thumbname, 'public');
  52. $thumbUrl = $disk->url($thumbFile);
  53. $media->thumbnail_url = $thumbUrl;
  54. $media->cdn_url = $url;
  55. $media->optimized_url = $url;
  56. $media->replicated_at = now();
  57. $media->save();
  58. if($media->status_id) {
  59. Cache::forget('status:transformer:media:attachments:' . $media->status_id);
  60. }
  61. }
  62. protected function remoteToCloud($media)
  63. {
  64. $url = $media->remote_url;
  65. if(!Helpers::validateUrl($url)) {
  66. return;
  67. }
  68. $head = $this->head($media->remote_url);
  69. $mimes = [
  70. 'image/jpeg',
  71. 'image/png',
  72. 'video/mp4'
  73. ];
  74. $mime = $head['mime'];
  75. $max_size = (int) config('pixelfed.max_photo_size') * 1000;
  76. $media->size = $head['length'];
  77. $media->remote_media = true;
  78. $media->save();
  79. if(!in_array($mime, $mimes)) {
  80. return;
  81. }
  82. if($head['length'] == $max_size) {
  83. return;
  84. }
  85. switch ($mime) {
  86. case 'image/png':
  87. $ext = '.png';
  88. break;
  89. case 'image/gif':
  90. $ext = '.gif';
  91. break;
  92. case 'image/jpeg':
  93. $ext = '.jpg';
  94. break;
  95. case 'video/mp4':
  96. $ext = '.mp4';
  97. break;
  98. }
  99. $base = MediaPathService::get($media->profile);
  100. $path = Str::random(40) . $ext;
  101. $tmpBase = storage_path('app/remcache/');
  102. $tmpPath = $media->profile_id . '-' . $path;
  103. $tmpName = $tmpBase . $tmpPath;
  104. $data = file_get_contents($url, false, null, 0, $head['length']);
  105. file_put_contents($tmpName, $data);
  106. $hash = hash_file('sha256', $tmpName);
  107. $disk = Storage::disk(config('filesystems.cloud'));
  108. $file = $disk->putFileAs($base, new File($tmpName), $path, 'public');
  109. $permalink = $disk->url($file);
  110. $media->cdn_url = $permalink;
  111. $media->original_sha256 = $hash;
  112. $media->replicated_at = now();
  113. $media->save();
  114. if($media->status_id) {
  115. Cache::forget('status:transformer:media:attachments:' . $media->status_id);
  116. }
  117. unlink($tmpName);
  118. }
  119. }