{"id":252763,"date":"2025-10-05T09:40:35","date_gmt":"2025-10-05T09:40:35","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/r2-media-offload\/"},"modified":"2025-10-05T18:39:16","modified_gmt":"2025-10-05T18:39:16","slug":"yctvn-media-offload-cloudflare-r2","status":"publish","type":"plugin","link":"https:\/\/mn.wordpress.org\/plugins\/yctvn-media-offload-cloudflare-r2\/","author":23368691,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.0.2","stable_tag":"1.0.2","tested":"6.8.5","requires":"5.0","requires_php":"8.0","requires_plugins":null,"header_name":"Yctvn Media Offload for Cloudflare R2","header_author":"kangta911","header_description":"Offload WordPress media files to Cloudflare R2 Storage","assets_banners_color":"3b4459","last_updated":"2025-10-05 18:39:16","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/www.buymeacoffee.com\/kangta911","header_plugin_uri":"","header_author_uri":"","rating":5,"author_block_rating":0,"active_installs":100,"downloads":1052,"num_ratings":3,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"kangta911","date":"2025-10-05 09:42:44"},"1.0.1":{"tag":"1.0.1","author":"kangta911","date":"2025-10-05 11:45:01"},"1.0.2":{"tag":"1.0.2","author":"kangta911","date":"2025-10-05 18:39:16"}},"upgrade_notice":{"1.0.2":"<p>Major UX improvements! AJAX settings save, enhanced bulk sync UI with real-time progress tracking and color-coded logs. Highly recommended update for better user experience.<\/p>","1.0.1":"<p>Bug fix release. Fixes plugin activation issue in some environments.<\/p>","1.0.0":"<p>Initial release of Yctvn Media Offload for Cloudflare R2.<\/p>"},"ratings":{"1":0,"2":0,"3":0,"4":0,"5":3},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3373110,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3373110,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3373110,"resolution":"1544x500","location":"assets","locale":""},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3373110,"resolution":"772x250","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3373110,"resolution":"1","location":"assets","locale":""},"screenshot-10.png":{"filename":"screenshot-10.png","revision":3373110,"resolution":"10","location":"assets","locale":""},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3373110,"resolution":"2","location":"assets","locale":""},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3373110,"resolution":"3","location":"assets","locale":""},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3373110,"resolution":"4","location":"assets","locale":""},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3373110,"resolution":"5","location":"assets","locale":""},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3373110,"resolution":"6","location":"assets","locale":""},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3373110,"resolution":"7","location":"assets","locale":""},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3373110,"resolution":"8","location":"assets","locale":""},"screenshot-9.png":{"filename":"screenshot-9.png","revision":3373110,"resolution":"9","location":"assets","locale":""}},"screenshots":{"1":"Step 1: Create R2 bucket in Cloudflare dashboard","2":"Step 2: Get your Account ID from R2 dashboard","3":"Step 3: Create API token with Read &amp; Write permissions","4":"Step 4: Copy Access Key ID and Secret Access Key","5":"Step 5: Configure Public URL or custom domain","6":"Plugin settings page - Enter R2 credentials","7":"Plugin settings - Auto upload and URL rewrite options","8":"Bulk sync interface showing upload progress","9":"Media library with R2\/CDN URLs","10":"Debug information and sync status panel"},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[3863,3882,84,19386,2216],"plugin_category":[50,59],"plugin_contributors":[248767],"plugin_business_model":[],"class_list":["post-252763","plugin","type-plugin","status-publish","hentry","plugin_tags-cdn","plugin_tags-cloudflare","plugin_tags-media","plugin_tags-object-storage","plugin_tags-storage","plugin_category-media","plugin_category-utilities-and-tools","plugin_contributors-kangta911","plugin_committers-kangta911"],"banners":{"banner":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/banner-772x250.png?rev=3373110","banner_2x":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/banner-1544x500.png?rev=3373110","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/icon-128x128.png?rev=3373110","icon_2x":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/icon-256x256.png?rev=3373110","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-1.png?rev=3373110","caption":"Step 1: Create R2 bucket in Cloudflare dashboard"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-2.png?rev=3373110","caption":"Step 2: Get your Account ID from R2 dashboard"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-3.png?rev=3373110","caption":"Step 3: Create API token with Read &amp; Write permissions"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-4.png?rev=3373110","caption":"Step 4: Copy Access Key ID and Secret Access Key"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-5.png?rev=3373110","caption":"Step 5: Configure Public URL or custom domain"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-6.png?rev=3373110","caption":"Plugin settings page - Enter R2 credentials"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-7.png?rev=3373110","caption":"Plugin settings - Auto upload and URL rewrite options"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-8.png?rev=3373110","caption":"Bulk sync interface showing upload progress"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-9.png?rev=3373110","caption":"Media library with R2\/CDN URLs"},{"src":"https:\/\/ps.w.org\/yctvn-media-offload-cloudflare-r2\/assets\/screenshot-10.png?rev=3373110","caption":"Debug information and sync status panel"}],"raw_content":"<!--section=description-->\n<p><strong>Yctvn Media Offload for Cloudflare R2<\/strong> seamlessly integrates your WordPress media library with Cloudflare R2 Storage, providing enterprise-grade CDN delivery at a fraction of the cost of traditional solutions.<\/p>\n\n<p><strong>\ud83d\udcf8 New to Cloudflare R2?<\/strong> Check out the Screenshots section for a complete visual setup guide with step-by-step instructions!<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>Automatic Media Upload<\/strong>: Automatically upload new media files to R2 storage as they're added to WordPress<\/li>\n<li><strong>Bulk Sync<\/strong>: Migrate existing media library to R2 with one-click bulk sync<\/li>\n<li><strong>CDN URL Rewriting<\/strong>: Serve all media from Cloudflare's global CDN network<\/li>\n<li><strong>Image Size Support<\/strong>: Upload and serve all WordPress image sizes including thumbnails<\/li>\n<li><strong>Responsive Images<\/strong>: Full support for srcset and responsive images<\/li>\n<li><strong>Post Content Rewriting<\/strong>: Automatically rewrite image URLs in post content<\/li>\n<li><strong>AWS Signature V4<\/strong>: Secure authentication using industry-standard protocols<\/li>\n<li><strong>Debug Mode<\/strong>: Comprehensive logging for troubleshooting<\/li>\n<\/ul>\n\n<h4>Why Choose R2 Storage?<\/h4>\n\n<ul>\n<li><strong>Cost Effective<\/strong>: No egress fees - pay only for storage<\/li>\n<li><strong>Global Performance<\/strong>: Leverage Cloudflare's worldwide CDN network<\/li>\n<li><strong>S3 Compatible<\/strong>: Works with standard S3 APIs<\/li>\n<li><strong>Reliability<\/strong>: Enterprise-grade infrastructure with 99.9% uptime SLA<\/li>\n<\/ul>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li>WordPress 5.0 or higher<\/li>\n<li>PHP 8.0 or higher (compatible with 8.0, 8.1, 8.2, 8.3, 8.4)<\/li>\n<li>Cloudflare account with R2 enabled<\/li>\n<li>R2 API credentials (Access Key ID and Secret Access Key)<\/li>\n<\/ul>\n\n<h4>Getting Started<\/h4>\n\n<p><strong>Visual Guide:<\/strong> See the Screenshots section below for a complete step-by-step visual guide!<\/p>\n\n<p>Follow these 3 simple steps to connect your WordPress site to Cloudflare R2:<\/p>\n\n<p><strong>Step 1: Create R2 Bucket<\/strong>\n1. Log in to <a href=\"https:\/\/dash.cloudflare.com\/\">Cloudflare Dashboard<\/a>\n2. Click on \"R2\" in the left sidebar\n3. Click \"Create bucket\"\n4. Enter a unique bucket name (e.g., \"my-wordpress-media\")\n5. Choose a location (optional)\n6. Click \"Create bucket\"<\/p>\n\n<p><strong>Step 2: Get Your Credentials<\/strong>\nYou need 4 pieces of information from Cloudflare:<\/p>\n\n<p><em>A. Account ID:<\/em>\n- In R2 dashboard, look at the top right corner\n- Copy the \"Account ID\" (format: 32 alphanumeric characters)<\/p>\n\n<p><em>B. Access Key ID &amp; Secret Access Key:<\/em>\n1. In R2 dashboard, click \"Manage R2 API Tokens\" \n2. Click \"Create API token\"\n3. Give it a name (e.g., \"WordPress Media Plugin\")\n4. Under Permissions, select \"Object Read &amp; Write\"\n5. (Optional) Under \"Specify bucket(s)\", you can limit to your specific bucket\n6. Click \"Create API token\"\n7. <strong>IMPORTANT<\/strong>: Copy and save both:\n   - Access Key ID (shows immediately)\n   - Secret Access Key (shows only once - save it now!)<\/p>\n\n<p><em>C. Bucket Name:<\/em>\n- The name you created in Step 1 (e.g., \"my-wordpress-media\")<\/p>\n\n<p><em>D. Public URL (CDN URL):<\/em>\n- Go to your R2 bucket \u2192 Settings\n- Under \"Public access\", click \"Allow Access\"\n- Your public URL will be: <code>https:\/\/pub-[hash].r2.dev<\/code>\n- OR connect a custom domain under \"Custom Domains\" (e.g., <code>https:\/\/cdn.yoursite.com<\/code>)<\/p>\n\n<p><strong>Step 3: Configure Plugin<\/strong>\n1. Install and activate this plugin\n2. Go to Settings \u2192 Yctvn Media Offload\n3. Enter all 4 credentials from Step 2:\n   - Account ID\n   - Access Key ID\n   - Secret Access Key\n   - Bucket Name\n   - Public URL (your R2 public URL or custom domain)\n4. Check \"Auto Offload\" to automatically upload new media\n5. Check \"Enable URL Rewrite\" to serve media from R2\/CDN\n6. Click \"Save Settings\"\n7. Use \"Bulk Sync\" to upload existing media<\/p>\n\n<h3>Additional Information<\/h3>\n\n<h4>Support<\/h4>\n\n<p>For support, please use the WordPress.org support forum.<\/p>\n\n<h4>Buy Me a Coffee<\/h4>\n\n<p>If you find this plugin helpful, consider <a href=\"https:\/\/www.buymeacoffee.com\/kangta911\">buying me a coffee<\/a> \u2615<\/p>\n\n<p>Your support helps maintain and improve this plugin!<\/p>\n\n<h4>Contributing<\/h4>\n\n<p>This plugin is open source and welcomes contributions from the community.<\/p>\n\n<h4>Privacy<\/h4>\n\n<p>This plugin does not collect any personal data. Media files are transferred directly between your WordPress site and your Cloudflare R2 account.<\/p>\n\n<!--section=installation-->\n<h4>Automatic Installation<\/h4>\n\n<ol>\n<li>Go to Plugins \u2192 Add New in your WordPress admin<\/li>\n<li>Search for \"Yctvn Media Offload for Cloudflare R2\"<\/li>\n<li>Click \"Install Now\" and then \"Activate\"<\/li>\n<li>Go to Settings \u2192 Yctvn Media Offload to configure<\/li>\n<\/ol>\n\n<h4>Manual Installation<\/h4>\n\n<ol>\n<li>Download the plugin ZIP file<\/li>\n<li>Go to Plugins \u2192 Add New \u2192 Upload Plugin<\/li>\n<li>Choose the ZIP file and click \"Install Now\"<\/li>\n<li>Activate the plugin<\/li>\n<li>Go to Settings \u2192 Yctvn Media Offload to configure<\/li>\n<\/ol>\n\n<h4>Configuration<\/h4>\n\n<h4>Detailed Setup Instructions<\/h4>\n\n<p><strong>Finding Your Account ID:<\/strong>\n1. Go to <a href=\"https:\/\/dash.cloudflare.com\/\">Cloudflare Dashboard<\/a>\n2. Click \"R2\" in the sidebar\n3. Your Account ID is displayed on the right side (32-character string)\n4. Example format: <code>a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6<\/code><\/p>\n\n<p><strong>Creating API Tokens:<\/strong>\n1. In R2 dashboard, click \"Manage R2 API Tokens\"\n2. Click \"Create API token\"\n3. Token name: Enter any name (e.g., \"WordPress Plugin\")\n4. Permissions: Select \"Object Read &amp; Write\"\n5. Bucket scope: Choose \"Apply to specific buckets\" or \"All buckets\"\n6. TTL: Leave as \"Forever\" or set expiration\n7. Click \"Create API token\"\n8. <strong>Save these immediately (Secret only shows once!):<\/strong>\n   - Access Key ID: <code>4e65xxxxxxxxxxxxxx<\/code> (20 chars)\n   - Secret Access Key: <code>tbral5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<\/code> (40 chars)<\/p>\n\n<p><strong>Getting Public\/CDN URL:<\/strong><\/p>\n\n<p><em>Option 1: Use R2.dev subdomain (easiest):<\/em>\n1. Go to your bucket \u2192 Settings\n2. Under \"Public access\", click \"Allow Access\"\n3. Copy the URL: <code>https:\/\/pub-xxxxx.r2.dev<\/code><\/p>\n\n<p><em>Option 2: Custom domain (recommended):<\/em>\n1. In your bucket, go to \"Settings\" \u2192 \"Custom Domains\"\n2. Click \"Connect Domain\"\n3. Enter your subdomain: <code>cdn.yoursite.com<\/code>\n4. Add DNS record as instructed by Cloudflare\n5. Wait for verification (may take a few minutes)\n6. Use <code>https:\/\/cdn.yoursite.com<\/code> as your Public URL<\/p>\n\n<p><strong>Plugin Settings Explained:<\/strong>\n- <strong>Account ID<\/strong>: Your Cloudflare account identifier\n- <strong>Access Key ID<\/strong>: API token public key\n- <strong>Secret Access Key<\/strong>: API token private key (keep secure!)\n- <strong>Bucket Name<\/strong>: Name of your R2 bucket\n- <strong>Public URL<\/strong>: R2.dev URL or custom domain\n- <strong>Auto Offload<\/strong>: Upload new media automatically to R2\n- <strong>URL Rewrite<\/strong>: Serve all media from R2\/CDN instead of local\n- <strong>Delete Local Files<\/strong>: Remove files from server after upload (saves space)\n- <strong>Upload Mode<\/strong>: \n  - \"Full Image Only\" = faster, uploads only main image\n  - \"All Sizes\" = uploads all thumbnails too<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id='is%20this%20plugin%20free%3F'><h3>Is this plugin free?<\/h3><\/dt>\n<dd><p>Yes, the plugin is completely free. You only pay for Cloudflare R2 storage usage.<\/p><\/dd>\n<dt id='what%20are%20the%20r2%20storage%20costs%3F'><h3>What are the R2 storage costs?<\/h3><\/dt>\n<dd><p>Cloudflare R2 charges $0.015 per GB per month for storage with no egress fees. Check Cloudflare's website for current pricing.<\/p><\/dd>\n<dt id='does%20it%20work%20with%20custom%20image%20sizes%3F'><h3>Does it work with custom image sizes?<\/h3><\/dt>\n<dd><p>Yes, the plugin uploads all registered WordPress image sizes including custom sizes defined by themes or plugins.<\/p><\/dd>\n<dt id='can%20i%20keep%20local%20copies%20of%20files%3F'><h3>Can I keep local copies of files?<\/h3><\/dt>\n<dd><p>Yes, you can choose whether to delete local files after upload or keep them as backup.<\/p><\/dd>\n<dt id='is%20it%20compatible%20with%20other%20cdn%20plugins%3F'><h3>Is it compatible with other CDN plugins?<\/h3><\/dt>\n<dd><p>The plugin rewrites media URLs to use R2\/CDN URLs. It may conflict with other CDN plugins that also rewrite URLs.<\/p><\/dd>\n<dt id='what%20happens%20if%20i%20deactivate%20the%20plugin%3F'><h3>What happens if I deactivate the plugin?<\/h3><\/dt>\n<dd><p>Media URLs will revert to local URLs. Files already uploaded to R2 remain there. You can reactivate anytime to resume using R2.<\/p><\/dd>\n<dt id='can%20i%20use%20a%20custom%20domain%20for%20cdn%3F'><h3>Can I use a custom domain for CDN?<\/h3><\/dt>\n<dd><p>Yes, you can configure a custom domain (like cdn.yourdomain.com) to point to your R2 bucket.<\/p><\/dd>\n<dt id='does%20it%20support%20webp%20images%3F'><h3>Does it support WebP images?<\/h3><\/dt>\n<dd><p>Yes, the plugin supports all file types that WordPress accepts, including WebP images.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>New: AJAX-based settings save - no page reload required<\/li>\n<li>New: Real-time save confirmation appears below Save button<\/li>\n<li>New: Enhanced Bulk Sync UI with visual progress bar<\/li>\n<li>New: Color-coded terminal-style sync logs (info, success, error, warning)<\/li>\n<li>New: Live sync statistics (processed count, success\/error tracking)<\/li>\n<li>Improved: Settings page UX - notifications stay in place without page refresh<\/li>\n<li>Improved: Bulk sync feedback - see each file upload in real-time<\/li>\n<li>Improved: Progress tracking with percentage and file counter<\/li>\n<li>Enhanced: Better user experience with instant feedback on all actions<\/li>\n<li>Fixed: Settings save now shows status immediately without reloading<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed: Plugin activation issue when debug files are missing<\/li>\n<li>Improved: Added file existence check for debug\/test files<\/li>\n<li>Enhanced: Better error handling for development mode<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Automatic media upload to R2<\/li>\n<li>Bulk sync for existing media<\/li>\n<li>CDN URL rewriting<\/li>\n<li>Support for all image sizes<\/li>\n<li>Responsive image support<\/li>\n<li>Post content rewriting<\/li>\n<li>Debug logging<\/li>\n<\/ul>","raw_excerpt":"Automatically offload your WordPress media library to Cloudflare R2 Storage for improved performance and reduced hosting costs.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/252763","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=252763"}],"author":[{"embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/kangta911"}],"wp:attachment":[{"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=252763"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=252763"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=252763"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=252763"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=252763"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/mn.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=252763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}