Cos.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <?php
  2. namespace App\Libraries\ChunkedUpload\Disks;
  3. use App\Libraries\ChunkedUpload\Contacts\ChunkedUploadContact;
  4. use App\Libraries\ChunkedUpload\Exceptions\UploadFailedException;
  5. use App\Services\File\Upload\ProgressBar;
  6. use Illuminate\Http\UploadedFile;
  7. use Illuminate\Support\Facades\Log;
  8. use Qcloud\Cos\Client;
  9. use QCloud\COSSTS\Sts;
  10. class Cos implements ChunkedUploadContact
  11. {
  12. public function upload(UploadedFile $file, string $savePath, string $name, ?ProgressBar $progressBar): string
  13. {
  14. $pathname = sprintf("%s/%s", $savePath, $name);
  15. $cosClient = new Client([
  16. 'region' => config('filesystems.disks.cos.region'),
  17. 'credentials' => [
  18. 'secretId' => config('filesystems.disks.cos.secret_id'),
  19. 'secretKey' => config('filesystems.disks.cos.secret_key')
  20. ]
  21. ]);
  22. try {
  23. $notUploadedSize = $file->getSize();
  24. $options = [
  25. 'PartSize' => 1 * 1024 * 1024,
  26. 'Progress' => function ($totalSize, $uploadedSize) use (&$notUploadedSize, $progressBar) {
  27. $partSize = $uploadedSize - ($totalSize - $notUploadedSize);
  28. $notUploadedSize = $totalSize - $uploadedSize;
  29. $progressBar?->increment($partSize);
  30. },
  31. 'ACL' => 'private',
  32. ];
  33. $cosClient->upload(
  34. sprintf("%s-%s", config('filesystems.disks.cos.bucket'), config('filesystems.disks.cos.app_id')),
  35. $pathname,
  36. fopen($file->getRealPath(), 'rb'),
  37. $options,
  38. );
  39. if ($notUploadedSize > 0) {
  40. $progressBar?->increment($notUploadedSize);
  41. }
  42. } catch (\Exception $exception) {
  43. Log::error('File upload failed messge:' . $exception->getMessage());
  44. throw new UploadFailedException("File upload failed.");
  45. }
  46. return $pathname;
  47. }
  48. /**
  49. * 获取临时密钥
  50. * @return array
  51. */
  52. public function getTempKeys(string $pathPrefix = ''): array
  53. {
  54. $sts = new Sts();
  55. $cosConfig = config('filesystems.disks.cos');
  56. $bucket = $cosConfig['bucket'] . '-' . $cosConfig['app_id'];
  57. $config = [
  58. 'url' => 'https://sts.tencentcloudapi.com/',
  59. 'secretId' => $cosConfig['secret_id'],
  60. 'secretKey' => $cosConfig['secret_key'],
  61. 'bucket' => $bucket,
  62. 'region' => $cosConfig['region'],
  63. 'durationSeconds' => 7200, // 密钥有效期(秒)
  64. 'allowPrefix' => [$pathPrefix . '/*'], // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径,例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
  65. // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
  66. 'allowActions' => [
  67. // 简单上传
  68. 'name/cos:PutObject',
  69. 'name/cos:PostObject',
  70. // 分片上传
  71. 'name/cos:InitiateMultipartUpload',
  72. 'name/cos:ListMultipartUploads',
  73. 'name/cos:ListParts',
  74. 'name/cos:UploadPart',
  75. 'name/cos:CompleteMultipartUpload'
  76. ],
  77. // 临时密钥生效条件,关于condition的详细设置规则和COS支持的condition类型可以参考 https://cloud.tencent.com/document/product/436/71306
  78. "condition" => []
  79. ];
  80. $data = $sts->getTempKeys($config);
  81. $data['bucket'] = $bucket;
  82. $data['region'] = $cosConfig['region'];
  83. $data['pathPrefix'] = $pathPrefix;
  84. return $data;
  85. }
  86. }