WP Manifestindependent plugin directory
manifest / media / wp-s3-media-offload-plugin

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

1stars
0forks

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.zip

Readme

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


فهرست مطالب

  1. معرفی
  2. قابلیت‌ها
  3. معماری
  4. ساختار پوشه‌ها
  5. نصب و راه‌اندازی
  6. پیکربندی سرویس‌های رایج
  7. آموزش کار با پلاگین
  8. هوک‌ها و جریان کار
  9. امنیت
  10. مهاجرت فایل‌های قدیمی
  11. حذف پلاگین
  12. عیب‌یابی
  13. توسعه

معرفی

به‌صورت پیش‌فرض وردپرس همه رسانه‌ها را در 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). کلاس‌ها زیر namespace WpS3MediaOffload\ قرار می‌گیرند و Composer از طریق classmap آن‌ها را autoload می‌کند (سازگار با نام‌گذاری WPCS و در عین حال ساختار OOP واضح).


نصب و راه‌اندازی

۱. نصب وابستگی‌ها

داخل پوشه پلاگین:

cd WP-S3-Media-Offload-Plugin
composer install --no-dev --optimize-autoloader

۲. فعال‌سازی در وردپرس

  1. پوشه پلاگین را در wp-content/plugins/wp-s3-media-offload قرار دهید
    (یا از همین مسیر به صورت symlink/کپی استفاده کنید).
  2. از منوی Plugins پلاگین را Activate کنید.
  3. به منوی اصلی رسانه 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 وارد کنید.


آموزش کار با پلاگین

آپلود فایل جدید

  1. تنظیمات را ذخیره و Test Connection را موفق کنید.
  2. از Media → Add New فایل آپلود کنید.
  3. وردپرس سایزهای تصویر را می‌سازد؛ پلاگین همه فایل‌ها را به S3 می‌فرستد.
  4. در صورت فعال بودن «حذف فایل محلی»، بعد از تأیید ETag/وضعیت موفق، فایل از دیسک سرور پاک می‌شود.
  5. 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های جاسازی‌شده در محتوا (پیشرفته)

جریان آپلود موفق:

  1. وردپرس فایل را موقتاً در uploads می‌نویسد و metadata می‌سازد.
  2. Uploader برای هر فایل (اصلی + سایزها) PutObject استریمی می‌زند.
  3. در صورت موفقیت، _s3_offload_key و _s3_offload_bucket ذخیره می‌شوند.
  4. اگر remove_local فعال باشد و پاسخ S3 معتبر باشد، فایل لوکال حذف می‌شود.
  5. 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 ندارند:

  1. لیست attachmentهای باقی‌مانده محاسبه می‌شود.
  2. مهاجرت به صورت Batch (پیش‌فرض ۲۰ فایل در هر درخواست AJAX) اجرا می‌شود تا از timeout جلوگیری شود.
  3. Progress bar وضعیت را نشان می‌دهد.
  4. در صورت خطا روی یک فایل، مهاجرت ادامه می‌یابد و خطا لاگ می‌شود.

حذف پلاگین

فایل 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 domain wp-s3-media-offload
  • مدیریت خطا با WP_Error

مراحل پیاده‌سازی (roadmap توسعه)

  1. ساختار پوشه‌ها + composer.json + bootstrap + README
  2. کلاس S3_Client
  3. صفحه تنظیمات ادمین
  4. هوک‌های آپلود و حذف
  5. بازنویسی URL
  6. ابزار Migration

همه مراحل بالا در نسخه ۱.۰.۰ پیاده‌سازی شده‌اند.

دستورهای مفید

composer install
composer dump-autoload -o

نکات مهم تصمیم‌گیری معماری

  1. فقط S3 از AWS SDK نگه داشته می‌شود تا حجم پلاگین مناسب بماند.
  2. فایل لوکال فقط بعد از تأیید آپلود حذف می‌شود تا fallback امن داشته باشید.
  3. CDN Domain اگر پر باشد همیشه بر Endpoint اولویت دارد.
  4. ACL اختیاری است چون همه ارائه‌دهندگان S3-compatible از ACL پشتیبانی نمی‌کنند.
  5. Migration دسته‌ای از timeout و memory exhaustion جلوگیری می‌کند.

ساخته‌شده برای محیط‌های وردپرس ۶ و فضای ابری سازگار با S3.

Read the full README on GitHub →