AliyunOss.php 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <?php
  2. namespace app\common\library;
  3. use OSS\Core\OssException;
  4. use OSS\OssClient;
  5. use think\Config;
  6. use think\Log;
  7. /**
  8. * 阿里云 OSS:上传本地文件,返回可访问 URL(对象建议 public-read,或依赖 Bucket 读策略)。
  9. */
  10. class AliyunOss
  11. {
  12. /**
  13. * @param string $localPath 本地文件绝对路径
  14. * @param string $objectKey OSS 对象键,如 xinhua/2026/05/06/订单号_1.pdf(勿以 / 开头)
  15. * @return string 成功返回 https 开头完整 URL;失败返回空串
  16. */
  17. public static function uploadLocalFile(string $localPath, string $objectKey): string
  18. {
  19. $objectKey = ltrim(str_replace('\\', '/', $objectKey), '/');
  20. if ($objectKey === '' || !is_file($localPath) || !is_readable($localPath)) {
  21. return '';
  22. }
  23. $cfg = Config::get('oss');
  24. if (!is_array($cfg) || (isset($cfg['enabled']) && $cfg['enabled'] === false)) {
  25. return '';
  26. }
  27. $id = trim((string)($cfg['accessKeyId'] ?? ''));
  28. $secret = trim((string)($cfg['accessKeySecret'] ?? ''));
  29. $endpoint = trim((string)($cfg['endpoint'] ?? ''));
  30. $bucket = trim((string)($cfg['bucket'] ?? ''));
  31. if ($id === '' || $secret === '' || $endpoint === '' || $bucket === '') {
  32. return '';
  33. }
  34. if (!class_exists(OssClient::class)) {
  35. Log::write('AliyunOss: OssClient 类不存在,请执行 composer install', 'error');
  36. return '';
  37. }
  38. try {
  39. $ossClient = new OssClient($id, $secret, $endpoint);
  40. $ossClient->uploadFile($bucket, $objectKey, $localPath);
  41. try {
  42. $ossClient->putObjectAcl($bucket, $objectKey, OssClient::OSS_ACL_TYPE_PUBLIC_READ);
  43. } catch (\Throwable $e) {
  44. Log::write('AliyunOss: putObjectAcl 失败(可改 Bucket 策略放行读): ' . $e->getMessage(), 'notice');
  45. }
  46. return self::buildPublicUrl($cfg, $objectKey);
  47. } catch (OssException $e) {
  48. Log::write('AliyunOss 上传失败: ' . $e->getMessage(), 'error');
  49. } catch (\Throwable $e) {
  50. Log::write('AliyunOss 上传异常: ' . $e->getMessage(), 'error');
  51. }
  52. return '';
  53. }
  54. /**
  55. * @param array<string, mixed> $cfg
  56. */
  57. protected static function buildPublicUrl(array $cfg, string $objectKey): string
  58. {
  59. $base = trim((string)($cfg['public_base'] ?? ''));
  60. if ($base !== '') {
  61. return rtrim($base, '/') . '/' . $objectKey;
  62. }
  63. $host = trim((string)($cfg['host'] ?? ''));
  64. if ($host === '') {
  65. $bucket = trim((string)($cfg['bucket'] ?? ''));
  66. $ep = trim((string)($cfg['endpoint'] ?? ''));
  67. if ($bucket !== '' && $ep !== '') {
  68. $host = $bucket . '.' . $ep;
  69. }
  70. }
  71. if ($host === '') {
  72. return '';
  73. }
  74. $host = preg_replace('#^https?://#i', '', $host);
  75. return 'https://' . $host . '/' . $objectKey;
  76. }
  77. }