|
|
@@ -2,19 +2,27 @@
|
|
|
|
|
|
namespace Webkul\Admin\Http\Controllers;
|
|
|
|
|
|
-use Illuminate\Support\Facades\Storage;
|
|
|
+use Aws\S3\S3Client;
|
|
|
+use Illuminate\Support\Str;
|
|
|
use Webkul\Core\Traits\Sanitizer;
|
|
|
|
|
|
class TinyMCEController extends Controller
|
|
|
{
|
|
|
use Sanitizer;
|
|
|
|
|
|
+ /**
|
|
|
+ * S3 client instance.
|
|
|
+ *
|
|
|
+ * @var S3Client|null
|
|
|
+ */
|
|
|
+ protected $s3Client = null;
|
|
|
+
|
|
|
/**
|
|
|
* Storage folder path.
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- private $storagePath = 'tinymce';
|
|
|
+ private $storagePath = 'uploads';
|
|
|
|
|
|
/**
|
|
|
* Allowed image MIME types.
|
|
|
@@ -30,6 +38,30 @@ class TinyMCEController extends Controller
|
|
|
'image/webp',
|
|
|
];
|
|
|
|
|
|
+ /**
|
|
|
+ * Get S3 client instance (lazy-loaded).
|
|
|
+ *
|
|
|
+ * @return S3Client
|
|
|
+ */
|
|
|
+ protected function getS3Client()
|
|
|
+ {
|
|
|
+ if (is_null($this->s3Client)) {
|
|
|
+ $this->s3Client = new S3Client([
|
|
|
+ 'version' => 'latest',
|
|
|
+ 'region' => env('AWS_DEFAULT_REGION'),
|
|
|
+ 'credentials' => [
|
|
|
+ 'key' => env('AWS_ACCESS_KEY_ID'),
|
|
|
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
|
|
+ ],
|
|
|
+ 'http' => [
|
|
|
+ 'verify' => false,
|
|
|
+ ],
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $this->s3Client;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Upload file from tinymce.
|
|
|
*
|
|
|
@@ -57,7 +89,7 @@ class TinyMCEController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Store media.
|
|
|
+ * Store media to S3.
|
|
|
*
|
|
|
* @return array
|
|
|
*/
|
|
|
@@ -90,14 +122,45 @@ class TinyMCEController extends Controller
|
|
|
return ['error' => trans('admin::app.components.tinymce.errors.file-extension-mismatch')];
|
|
|
}
|
|
|
|
|
|
- $path = $file->store($this->storagePath);
|
|
|
+ // 生成 S3 存储路径
|
|
|
+ $fileName = Str::random(40) . '.' . $extension;
|
|
|
+ $path = $this->storagePath . '/' . date('Ym/d') . '/' . $fileName;
|
|
|
+
|
|
|
+ $body = file_get_contents($file->getRealPath());
|
|
|
+
|
|
|
+ // SVG 需要先消毒再上传
|
|
|
+ if ($mimeType === 'image/svg+xml') {
|
|
|
+ $body = $this->sanitizeSvgContent($body);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上传到 S3
|
|
|
+ $this->getS3Client()->putObject([
|
|
|
+ 'Bucket' => env('AWS_BUCKET'),
|
|
|
+ 'Key' => $path,
|
|
|
+ 'Body' => $body,
|
|
|
+ 'ContentType' => $mimeType,
|
|
|
+ ]);
|
|
|
|
|
|
- $this->sanitizeSVG($path, $mimeType);
|
|
|
+ $fileUrl = rtrim(env('AWS_URL', ''), '/') . '/' . ltrim($path, '/');
|
|
|
|
|
|
return [
|
|
|
'file' => $path,
|
|
|
'file_name' => $file->getClientOriginalName(),
|
|
|
- 'file_url' => Storage::url($path),
|
|
|
+ 'file_url' => $fileUrl,
|
|
|
];
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Sanitize SVG content (direct string version for S3 workflow).
|
|
|
+ *
|
|
|
+ * @param string $content
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function sanitizeSvgContent(string $content): string
|
|
|
+ {
|
|
|
+ $sanitizer = new \enshrined\svgSanitize\Sanitizer();
|
|
|
+ $sanitizer->removeRemoteReferences(true);
|
|
|
+
|
|
|
+ return $sanitizer->sanitize($content);
|
|
|
+ }
|
|
|
}
|