WP S3 Media Offload
Offload WordPress Media Library files to S3-compatible object storage (Amazon S3, Liara, ArvanCloud, MinIO, DigitalOcean Spaces, and more).
by WP S3 Media Offload · github.com/arashfadaee/wp-s3-media-offload-plugin · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/arashfadaee/wp-s3-media-offload-plugin/archive/refs/heads/main.zipReadme
WP S3 Media Offload
افزونه وردپرس برای انتقال فایلهای Media Library به فضای ذخیرهسازی سازگار با S3 (S3-Compatible Object Storage) و سرو کردن آنها از Endpoint یا CDN اختصاصی.
نام پلاگین: wp-s3-media-offload
Text Domain: wp-s3-media-offload
سازگاری: PHP 8.0+ · WordPress 6.x+
لایسنس: GPL-2.0-or-later
فهرست مطالب
- معرفی
- قابلیتها
- معماری
- ساختار پوشهها
- نصب و راهاندازی
- پیکربندی سرویسهای رایج
- آموزش کار با پلاگین
- هوکها و جریان کار
- امنیت
- مهاجرت فایلهای قدیمی
- حذف پلاگین
- عیبیابی
- توسعه
معرفی
بهصورت پیشفرض وردپرس همه رسانهها را در wp-content/uploads روی همان سرور ذخیره میکند. با رشد سایت، این کار باعث مصرف زیاد دیسک، کندی بکاپ و فشار روی سرور وب میشود.
WP S3 Media Offload هنگام آپلود در Media Library، فایل اصلی و تمام سایزهای تصویر را به باکت S3 (یا سرویس سازگار مثل Liara، ArvanCloud، MinIO، DigitalOcean Spaces، Amazon S3) میفرستد و URL نهایی را از دامنه Endpoint یا CDN برمیگرداند.
قابلیتها
- آپلود خودکار فایلهای جدید (تصویر و غیرتصویر) به S3
- پشتیبانی از Multipart / Stream برای فایلهای حجیم
- بازنویسی URL رسانه به Endpoint یا CDN سفارشی
- حذف فایل از S3 هنگام حذف از Media Library
- گزینه حذف فایل محلی پس از آپلود موفق
- Path-style و Virtual-hosted-style endpoint
- ACL اختیاری (
public-read) برای سرویسهایی که ACL را پشتیبانی میکنند - هدر
Cache-Controlبرای کش مرورگر - رمزنگاری Access Key / Secret در دیتابیس
- دکمه Test Connection در تنظیمات
- ابزار Migration دستهای برای فایلهای قدیمی
- Uninstall Hook برای پاکسازی اختیاری تنظیمات
- آماده ترجمه (i18n)
معماری
پلاگین به صورت Object-Oriented با namespace WpS3MediaOffload\ طراحی شده و وابستگیها از طریق Composer بارگذاری میشوند.
┌─────────────────────────────────────────────────────────────┐
│ wp-s3-media-offload.php │
│ (Bootstrap + Constants + Autoload) │
└────────────────────────────┬────────────────────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Settings │ │ Media_Hooks │
│ (Admin UI + │◄───────────│ (WP actions / │
│ Options API) │ │ filters) │
└───────┬────────┘ └───────┬────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ S3_Client │◄───────────│ Uploader │
│ (AWS SDK S3 │ │ (Upload / │
│ wrapper only) │ │ Delete / Meta)│
└────────────────┘ └───────┬────────┘
│
▼
┌────────────────┐
│ URL_Rewriter │
│ (CDN / S3 URL) │
└────────────────┘
│
▼
┌────────────────┐
│ Migrator │
│ (Batch AJAX) │
└────────────────┘
مسئولیت کلاسها
| کلاس | فایل | مسئولیت |
|---|---|---|
S3_Client |
includes/class-s3-client.php |
ساخت Aws\S3\S3Client، Put/Delete/List، تست اتصال |
Settings |
includes/class-settings.php |
صفحه تنظیمات، sanitize، nonce، AJAX Test Connection |
Uploader |
includes/class-uploader.php |
آپلود استریمی، ذخیره _s3_offload_key / _s3_offload_bucket، حذف local |
URL_Rewriter |
includes/class-url-rewriter.php |
ساخت URL نهایی (Path-style / Virtual-hosted / CDN) |
Media_Hooks |
includes/class-media-hooks.php |
اتصال به هوکهای وردپرس |
Migrator |
includes/class-migrator.php |
مهاجرت دستهای فایلهای قدیمی |
وابستگی AWS SDK
فقط سرویس S3 از aws/aws-sdk-php نگه داشته میشود تا حجم vendor کم بماند:
"scripts": {
"pre-autoload-dump": "Aws\\Script\\Composer\\Composer::removeUnusedServices"
},
"extra": {
"aws/aws-sdk-php": ["S3"]
}
ذخیره تنظیمات
همه تنظیمات در یک option به نام wp_s3_offload_settings (آرایه) ذخیره میشوند:
| کلید | توضیح |
|---|---|
access_key |
Access Key ID (رمزنگاریشده) |
secret_key |
Secret Access Key (رمزنگاریشده) |
bucket |
نام باکت |
region |
Region (میتواند خالی باشد) |
endpoint |
Endpoint URL سرویس |
cdn_domain |
دامنه CDN سفارشی (اختیاری) |
path_prefix |
پیشوند مسیر داخل باکت (مثلاً uploads) |
path_style |
استفاده از Path-style endpoint |
remove_local |
حذف فایل محلی بعد از آپلود موفق |
use_acl |
تنظیم ACL روی public-read |
remove_data_on_uninstall |
پاک کردن تنظیمات هنگام حذف پلاگین |
متادیتای پیوست
| Meta Key | مقدار |
|---|---|
_s3_offload_key |
مسیر کامل آبجکت داخل باکت |
_s3_offload_bucket |
نام باکت |
قوانین ساخت URL
- Path-style:
https://ENDPOINT/BUCKET/KEY - Virtual-hosted-style:
https://BUCKET.ENDPOINT/KEY - CDN سفارشی:
https://CDN_DOMAIN/KEY
ساختار پوشهها
WP-S3-Media-Offload-Plugin/
├── wp-s3-media-offload.php # فایل اصلی پلاگین (هدر + bootstrap)
├── uninstall.php # پاکسازی اختیاری هنگام حذف
├── composer.json # وابستگیها و autoload
├── README.md # مستندات
├── .gitignore
├── includes/ # کلاسهای هسته (namespace: WpS3MediaOffload)
│ ├── class-s3-client.php
│ ├── class-settings.php
│ ├── class-uploader.php
│ ├── class-url-rewriter.php
│ ├── class-media-hooks.php
│ └── class-migrator.php
├── assets/
│ ├── admin.css # استایل صفحه تنظیمات و progress bar
│ └── admin.js # Test Connection + Migration AJAX
├── languages/ # فایلهای ترجمه (.pot / .mo)
└── vendor/ # خروجی Composer (در Git نیست)
نام فایلها مطابق WordPress Coding Standards است (
class-*.php). کلاسها زیر namespaceWpS3MediaOffload\قرار میگیرند و Composer از طریقclassmapآنها را autoload میکند (سازگار با نامگذاری WPCS و در عین حال ساختار OOP واضح).
نصب و راهاندازی
۱. نصب وابستگیها
داخل پوشه پلاگین:
cd WP-S3-Media-Offload-Plugin
composer install --no-dev --optimize-autoloader
۲. فعالسازی در وردپرس
- پوشه پلاگین را در
wp-content/plugins/wp-s3-media-offloadقرار دهید
(یا از همین مسیر به صورت symlink/کپی استفاده کنید). - از منوی Plugins پلاگین را Activate کنید.
- به منوی اصلی رسانه S3 در پیشخوان وردپرس بروید.
۳. پر کردن تنظیمات
حداقل فیلدهای لازم:
- Access Key ID
- Secret Access Key
- Bucket Name
- Endpoint URL (برای سرویسهای غیر AWS ضروری است)
- Path/Prefix (مثلاً
uploads) - Use Path Style Endpoint (برای اکثر سرویسهای ایرانی و MinIO روشن باشد)
سپس روی Test Connection کلیک کنید. در صورت موفقیت، آپلودهای جدید به S3 میروند.
پیکربندی سرویسهای رایج
Liara Object Storage
| فیلد | مقدار نمونه |
|---|---|
| Endpoint | https://storage.iran.liara.space |
| Region | خالی یا طبق پنل |
| Path Style | فعال |
| ACL | بسته به پلن؛ در صورت خطا خاموش کنید |
ArvanCloud Object Storage
| فیلد | مقدار نمونه |
|---|---|
| Endpoint | https://s3.ir-thr-at1.arvanstorage.ir |
| Region | مطابق پنل (مثلاً ir-thr-at1) |
| Path Style | فعال |
Amazon S3
| فیلد | مقدار نمونه |
|---|---|
| Endpoint | خالی (SDK خودش میسازد) یا endpoint استاندارد region |
| Region | مثلاً eu-central-1 |
| Path Style | معمولاً غیرفعال |
| CDN | CloudFront domain در صورت نیاز |
MinIO / DigitalOcean Spaces
Endpoint و Bucket را از پنل کپی کنید، Path Style را برای MinIO معمولاً فعال بگذارید، و در صورت داشتن CDN دامنه را در فیلد CDN وارد کنید.
آموزش کار با پلاگین
آپلود فایل جدید
- تنظیمات را ذخیره و Test Connection را موفق کنید.
- از Media → Add New فایل آپلود کنید.
- وردپرس سایزهای تصویر را میسازد؛ پلاگین همه فایلها را به S3 میفرستد.
- در صورت فعال بودن «حذف فایل محلی»، بعد از تأیید ETag/وضعیت موفق، فایل از دیسک سرور پاک میشود.
- URL نمایشدادهشده در Media Library از Endpoint یا CDN میآید.
حذف فایل
حذف پیوست از Media Library باعث حذف آبجکت متناظر (و سایزها) از S3 نیز میشود.
فایلهای غیرتصویری
PDF، ZIP و سایر mime typeها از طریق هوک wp_handle_upload پوشش داده میشوند.
بازنویسی محتوا
فیلترهای wp_get_attachment_url، wp_get_attachment_image_src، wp_calculate_image_srcset و (در صورت فعال بودن) جایگزینی در the_content آدرسهای قدیمی لوکال را به URL ابری نگاشت میکنند.
هوکها و جریان کار
| هوک وردپرس | نقش در پلاگین |
|---|---|
wp_generate_attachment_metadata |
آپلود فایل اصلی + همه thumbnailها |
wp_handle_upload |
پوشش فایلهای غیرتصویری |
wp_update_attachment_metadata |
همگامسازی متادیتا و کلید S3 |
delete_attachment |
حذف آبجکت از S3 |
wp_get_attachment_url |
بازنویسی URL اصلی |
wp_get_attachment_image_src |
بازنویسی src تصویر |
wp_calculate_image_srcset |
بازنویسی srcset |
the_content |
جایگزینی URLهای جاسازیشده در محتوا (پیشرفته) |
جریان آپلود موفق:
- وردپرس فایل را موقتاً در
uploadsمینویسد و metadata میسازد. Uploaderبرای هر فایل (اصلی + سایزها) PutObject استریمی میزند.- در صورت موفقیت،
_s3_offload_keyو_s3_offload_bucketذخیره میشوند. - اگر
remove_localفعال باشد و پاسخ S3 معتبر باشد، فایل لوکال حذف میشود. URL_Rewriterاز این به بعد URL ابری را برمیگرداند.
امنیت
- Access Key و Secret Key با لایه رمزنگاری مبتنی بر کلیدهای وردپرس (
AUTH_KEY/SECURE_AUTH_KEY) در دیتابیس ذخیره میشوند. - در UI فقط چند کاراکتر آخر Secret نمایش داده میشود (mask).
- همه فرمهای ادمین دارای nonce و بررسی capability
manage_optionsهستند. - درخواستهای AJAX (Test Connection و Migration) nonce-protected هستند.
- ورودیها با
sanitize_text_field،esc_url_rawو مشابه sanitize میشوند؛ خروجی باesc_html/esc_attr/esc_urlچاپ میشود. - خطاها به صورت
WP_Errorمدیریت میشوند؛ در حالتWP_DEBUGجزئیات درerror_logثبت میشود.
مهاجرت فایلهای قدیمی
در صفحه تنظیمات، بخش Migration برای فایلهایی است که هنوز _s3_offload_key ندارند:
- لیست attachmentهای باقیمانده محاسبه میشود.
- مهاجرت به صورت Batch (پیشفرض ۲۰ فایل در هر درخواست AJAX) اجرا میشود تا از timeout جلوگیری شود.
- Progress bar وضعیت را نشان میدهد.
- در صورت خطا روی یک فایل، مهاجرت ادامه مییابد و خطا لاگ میشود.
حذف پلاگین
فایل uninstall.php فقط وقتی optionها را پاک میکند که در تنظیمات گزینه Remove data on uninstall فعال باشد. خود فایلهای روی S3 بهصورت پیشفرض حذف نمیشوند.
عیبیابی
| مشکل | بررسی |
|---|---|
| Notice مربوط به Composer | composer install را داخل پوشه پلاگین اجرا کنید |
| Test Connection ناموفق | Endpoint، Bucket، کلیدها، Path Style و Region را چک کنید |
| URL اشتباه | CDN Domain یا Path Style را بررسی کنید |
| خطای ACL | گزینه Use ACL را خاموش کنید (بعضی پلنهای Liara) |
| فایل لوکال پاک نمیشود | فقط بعد از آپلود موفق با ETag معتبر پاک میشود؛ گزینه را در تنظیمات چک کنید |
| تصویر در محتوا هنوز لوکال است | Migration را اجرا کنید یا صفحه را مجدد ذخیره کنید |
فعالسازی دیباگ در wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
لاگها معمولاً در wp-content/debug.log نوشته میشوند.
توسعه
استانداردها
- WordPress Coding Standards
- PHP 8.0+ با
declare(strict_types=1); - متنهای UI با
__()/esc_html__()و text domainwp-s3-media-offload - مدیریت خطا با
WP_Error
مراحل پیادهسازی (roadmap توسعه)
- ساختار پوشهها +
composer.json+ bootstrap + README - کلاس
S3_Client - صفحه تنظیمات ادمین
- هوکهای آپلود و حذف
- بازنویسی URL
- ابزار Migration
همه مراحل بالا در نسخه ۱.۰.۰ پیادهسازی شدهاند.
دستورهای مفید
composer install
composer dump-autoload -o
نکات مهم تصمیمگیری معماری
- فقط S3 از AWS SDK نگه داشته میشود تا حجم پلاگین مناسب بماند.
- فایل لوکال فقط بعد از تأیید آپلود حذف میشود تا fallback امن داشته باشید.
- CDN Domain اگر پر باشد همیشه بر Endpoint اولویت دارد.
- ACL اختیاری است چون همه ارائهدهندگان S3-compatible از ACL پشتیبانی نمیکنند.
- Migration دستهای از timeout و memory exhaustion جلوگیری میکند.
ساختهشده برای محیطهای وردپرس ۶ و فضای ابری سازگار با S3.