<?php | |
ini_set('display_errors', 1); | |
error_reporting(E_ALL); | |
/* ====================================================== | |
This script is NOT FULLY TESTED (not tested on Windows Server either) | |
USE AT YOUR OWN RISK - development environment Ubuntu Linux 14.04.3 LTS | |
The purpose of this script is for small websites and blogs | |
to have their existing media to work through Amazon S3 | |
There's a great plugin, WP Offload S3, that we'll be tapping | |
into...it works great for new media, but this is a quick | |
fix for EXISTING media - media added before you start | |
using WP Offload S3. | |
This script is not fully tested, but should be useful for | |
most situations. It does create a backup of your database, | |
though it's not tested to work 100% in all hosting scenarios. | |
Put this file in your WordPress root directory, where wp-config.php is. | |
You must also already have these 2 plugins installed and configured: | |
- https://wordpress.org/plugins/amazon-web-services/ | |
- https://wordpress.org/plugins/amazon-s3-and-cloudfront/ | |
TURN OFF CACHING if you have it on your site. Re-enable it after | |
everything is done. | |
====================================================== | |
STEPS | |
1) Manually upload all of your existing /wp-content/uploads/ files to the | |
Amazon S3 bucket (the bucket you configured WP Offload S3 to use for new images) | |
2) Add and configure plugins (the 2 listed above) | |
3) Run this script from the root directory of your WordPress site | |
====================================================== | |
Developer: TJ Nevis | |
Website: http://blog.TJNevis.com, http://NevisTechnology.com | |
More Info: http://blog.tjnevis.com/wordpress-and-amazon-s3-quick-fix-for-existing-media-to-be-served-on-amazon-s3/ | |
Last Updated: 04/19/2016 | |
====================================================== */ | |
require_once 'wp-config.php'; | |
require_once 'wp-content/plugins/amazon-s3-and-cloudfront/wordpress-s3.php'; | |
global $table_prefix; | |
echo '<h1>Move Existing Media to Amazon S3</h1>'; | |
echo '<h3>By TJ Nevis [<a href="http://NevisTechnology.com?ref=S3Script" target="_blank">NevisTechnology.com</a>] Detailed blog post <a href="http://blog.tjnevis.com/wp-offload-s3-quick-fix-for-existing-media/" target="_blank">here</a></h3>'; | |
/* ====================================================== | |
First step, we're going to back up the database and | |
save it in the the root directory of your site (where this file is) | |
====================================================== */ | |
$dbHost = $wpdb->dbhost; | |
$dbName = $wpdb->dbname; | |
$dbPassword = $wpdb->dbpassword; | |
$dbSaveFileLocation = dirname(__FILE__) . '/backup-' . date('Y-m-d-h:i:s', time()) . '.sql'; | |
$dbUser = $wpdb->dbuser; | |
exec("mysqldump --user=$dbUser --password=$dbPassword --host=$dbHost $dbName > $dbSaveFileLocation"); | |
/* ====================================================== | |
Let's get set up with by grabbing WP Offload S3 values | |
====================================================== */ | |
amazon_web_services_require_files(); // Thanks k0nG | |
$aws = new Amazon_Web_Services( __FILE__ ); // Thanks k0nG | |
$awsS3 = new Amazon_S3_And_CloudFront(__FILE__, $aws); // Thanks k0nG | |
$bucket = ( !empty( $awsS3->get_setting('cloudfront') ) ) ? $awsS3->get_setting('cloudfront') : $awsS3->get_setting('bucket'); // If you're using a CDN and the setting is saved, use that for CloudFront URL replcaement, otherwise use the S3 bucket name | |
$region = $awsS3->get_setting('region'); // Thanks k0nG | |
$folderPrefix = $awsS3->get_setting('object-prefix'); | |
/* ====================================================== | |
Check if the user is requesting to remove the existing media updates | |
====================================================== */ | |
if( isset($_GET['remove']) && $_GET['remove'] ) { // ?removeS3Update=true | |
if( $dbConnection = mysqli_connect($dbHost, $dbUser, $dbPassword, $dbName) ) { | |
$removeAmazonS3Info = "DELETE FROM " . $table_prefix . "postmeta WHERE meta_key = 'amazonS3_info';"; | |
$reversePostContentHref = updatePostContent( | |
'href', | |
$table_prefix . 'posts', | |
get_site_url( $wpdb->blogid ) . '/' . $folderPrefix, | |
"https://$bucket.s3.amazonaws.com/$folderPrefix", | |
true | |
); | |
$reversePostContentSrc = updatePostContent( | |
'src', | |
$table_prefix . 'posts', | |
get_site_url( $wpdb->blogid ) . '/' . $folderPrefix, | |
"https://$bucket.s3.amazonaws.com/$folderPrefix", | |
true | |
); | |
echo 'RUNNING COMMAND: ' . $removeAmazonS3Info . ' - '; | |
if( $dbConnection->query($removeAmazonS3Info) ) { | |
echo ' <strong>TRUE, ' . $dbConnection->affected_rows . ' rows affected</strong><br />'; | |
} | |
echo 'RUNNING COMMAND: ' . $reversePostContentHref . ' - '; | |
if( $dbConnection->query($reversePostContentHref) ) { | |
echo ' <strong>TRUE, ' . $dbConnection->affected_rows . ' rows affected</strong><br />'; | |
} | |
echo 'RUNNING COMMAND: ' . $reversePostContentSrc . ' - '; | |
if( $dbConnection->query($reversePostContentSrc) ) { | |
echo ' <strong>TRUE, ' . $dbConnection->affected_rows . ' rows affected</strong><br />'; | |
} | |
} | |
echo '<h3>DONE with removing records for WP Offload S3 - reverted back to serving from the local server</h3>'; | |
exit(); // Don't do the rest of the script | |
} | |
/* ====================================================== | |
Start fresh, delete data thatis from WP Offload S3 | |
====================================================== */ | |
$wpdb->delete($table_prefix . 'postmeta', | |
array( | |
'meta_key' => 'amazonS3_info' | |
) | |
); | |
/* ====================================================== | |
Grab the attachments from the database, we'll need | |
the meta_value (image name), and the post ID it's related to | |
====================================================== */ | |
$picturesToUpdate = $wpdb->get_results("SELECT * FROM " . $table_prefix . "postmeta WHERE meta_key = '_wp_attached_file'"); | |
foreach($picturesToUpdate as $picture) { | |
$pictureMetaData = serialize(array( | |
'bucket' => $bucket, | |
'key' => $folderPrefix . $picture->meta_value, | |
'region' => $region // Thanks k0nG | |
)); | |
/* ====================================================== | |
Now let's insert the record that WP Offload S3 looks for | |
to change the image URL to your S3 URL | |
====================================================== */ | |
$wpdb->insert($table_prefix . 'postmeta', | |
array( | |
'post_id' => $picture->post_id, | |
'meta_key' => 'amazonS3_info', | |
'meta_value' => $pictureMetaData | |
) | |
); | |
} | |
if( $dbConnection = mysqli_connect($dbHost, $dbUser, $dbPassword, $dbName) ) { | |
$hrefMySQLUpdate = updatePostContent( | |
'href', | |
$table_prefix . 'posts', | |
get_site_url( $wpdb->blogid ) . '/' . $folderPrefix, | |
"https://$bucket.s3.amazonaws.com/$folderPrefix" | |
); | |
$srcMySQLUpdate = updatePostContent( | |
'src', | |
$table_prefix . 'posts', | |
get_site_url( $wpdb->blogid ) . '/' . $folderPrefix, | |
"https://$bucket.s3.amazonaws.com/$folderPrefix" | |
); | |
echo 'RUNNING COMMAND: ' . $hrefMySQLUpdate . ' - '; | |
if( $dbConnection->query($hrefMySQLUpdate) ) { | |
echo ' <strong>TRUE, ' . $dbConnection->affected_rows . ' rows affected</strong><br />'; | |
} | |
echo 'RUNNING COMMAND: ' . $srcMySQLUpdate . ' - '; | |
if( $dbConnection->query($srcMySQLUpdate) ) { | |
echo ' <strong>TRUE, ' . $dbConnection->affected_rows . ' rows affected</strong><br />'; | |
} | |
} | |
echo '<h3>DONE with adding records for WP Offload S3 to recognize the image on S3</h3>'; | |
function updatePostContent($type, $table, $blog, $s3bucket, $reverse = FALSE) { | |
// $reverse is to remove the post_content updates and put them back to serving locally | |
$from = ( !$reverse ) ? $blog : $s3bucket; | |
$to = ( !$reverse ) ? $s3bucket : $blog; | |
return "UPDATE $table SET post_content = replace(post_content, '$type=\"$from', '$type=\"$to');"; | |
} | |
?> |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
k0nG
commented
Mar 17, 2016
Hi, Great script. I had a little trouble getting it to work as the amazon_web_services_require_files(); // Import AWS plugin classes.
$aws = new Amazon_Web_Services( __FILE__ );
$awsS3 = new Amazon_S3_And_CloudFront(__FILE__, $aws); Also i'm using an EU West bucket, you can also then get the bucket region using: $region = $awsS3->get_setting('region'); And update the attachment meta data update to: $pictureMetaData = serialize(array(
'bucket' => $bucket,
'key' => $folderPrefix . $picture->meta_value,
'region' => $region
)); |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
TJNevis
Apr 19, 2016
Hey,
Awesome. Thanks for the revision. I made the adjustments and used it on one of my sites. Works perfect.
Thanks again for the update.
I've updated the snippet.
Hey, Awesome. Thanks for the revision. I made the adjustments and used it on one of my sites. Works perfect. Thanks again for the update. I've updated the snippet. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
UseDotCom
Sep 22, 2016
This is amazing and it worked perfectly, thank you!
I was dreading figuring this out, you saved me a lot of time.
UseDotCom
commented
Sep 22, 2016
This is amazing and it worked perfectly, thank you! I was dreading figuring this out, you saved me a lot of time. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
phumpal
Nov 4, 2016
Thanks for this @TJNevis.
I tested this on Xenial with PHP 7 and one thing I might add is that MySQL functions have been deprecated as of PHP 5.5.0.
Use of mysqli extensions is recommended.
To update in vim for example
:%s/mysql_/mysqli_/gc
One note:
mysqli
expects two parameters otherwise there are warnings. For example continuing to use the procedural style on line 155
$db = mysqli_connect($dbHost, $dbUser, $dbPassword);
if($db) {
then on line 172
mysqli_query($db, $hrefMySQLUpdate)
and line 177
mysqli_query($db, $srcMySQLUpdate)
phumpal
commented
Nov 4, 2016
Thanks for this @TJNevis. I tested this on Xenial with PHP 7 and one thing I might add is that MySQL functions have been deprecated as of PHP 5.5.0. Use of mysqli extensions is recommended. To update in vim for example :%s/mysql_/mysqli_/gc One note:
$db = mysqli_connect($dbHost, $dbUser, $dbPassword);
if($db) { then on line 172 mysqli_query($db, $hrefMySQLUpdate) and line 177 mysqli_query($db, $srcMySQLUpdate) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
duchu
commented
Nov 30, 2016
remove query not working ? any idea why ? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
sidimar
Jan 13, 2017
Hi,
Great script, it's working perfect.
I wondering if you had the same issue I am having with PDFs. It's changed the PDFs URL to amazon (perfect) but now I have to change the links to PDFs. I am truing figure out a quick way to do that instead go through one by one.
Regards,
sidimar
commented
Jan 13, 2017
Hi, |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
reb0rn045
Jan 21, 2017
Hi, I am getting 500 error on running this file. I am using easy engine latest version on ubuntu. Can somebody help ?
reb0rn045
commented
Jan 21, 2017
Hi, I am getting 500 error on running this file. I am using easy engine latest version on ubuntu. Can somebody help ? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
atlasnetwork
Feb 6, 2017
Not sure if its a plugin that is causing this or what, but in some cases /wp-content/uploads is repeated in the replacement so it reads s3bucketurl.com/wp-content/uploads//wp-content/uploads/filename (with the two slashes).
Any idea on how to fix this?
Can I run a search and replace on the database for /wp-content/uploads//wp-content/uploads/ and replace with /wp-content/uploads/ ? What table/column would I run this on?
This seems to happen only when the file is in the wp-content/uploads root directory
** I ended up fixing this with UPDATE wp_postmeta SET meta_value = replace(meta_value, '/wp-content/uploads/', '');
atlasnetwork
commented
Feb 6, 2017
•
edited
edited
Not sure if its a plugin that is causing this or what, but in some cases /wp-content/uploads is repeated in the replacement so it reads s3bucketurl.com/wp-content/uploads//wp-content/uploads/filename (with the two slashes). Any idea on how to fix this? Can I run a search and replace on the database for /wp-content/uploads//wp-content/uploads/ and replace with /wp-content/uploads/ ? What table/column would I run this on? This seems to happen only when the file is in the wp-content/uploads root directory ** I ended up fixing this with UPDATE wp_postmeta SET meta_value = replace(meta_value, '/wp-content/uploads/', ''); |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
leedotpang
commented
Feb 21, 2017
You sir, are a gentleman, and a scholar. Thank you for sharing! |
vumhoang
commented
Mar 7, 2017
@TJNevis: Have you tried this with Offload S3 Lite? I am trying to do the same job but the php file doesn't work. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Silvercast
commented
Mar 7, 2017
I have the same interest. Let me know if it works with Lite @vumhoang |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
vumhoang
commented
Mar 14, 2017
@Silvercast: so far I couldn't make it work. :( |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
robalves-tpro
commented
May 9, 2017
Great! It's working perfectly. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dokomade99
May 12, 2017
I want to ask
How to setting amazon s3 in wordpress so it does not automatically to my cdn? I want to directly use a bucket that like ditutorial. But instead automatically to my cdn croudfront. Please help
I see the tutorial from your blog
dokomade99
commented
May 12, 2017
I want to ask How to setting amazon s3 in wordpress so it does not automatically to my cdn? I want to directly use a bucket that like ditutorial. But instead automatically to my cdn croudfront. Please help |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
raydoll
May 17, 2017
This was a huge help. I was literally just discussing doing this for a client of mine. I had to modify a bit for my situation but miles simpler than starting from scratch. Great work you put into this! Many thanks my man.
raydoll
commented
May 17, 2017
This was a huge help. I was literally just discussing doing this for a client of mine. I had to modify a bit for my situation but miles simpler than starting from scratch. Great work you put into this! Many thanks my man. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
crankeye
Jul 6, 2017
Much appreciated. Though the https://$bucket.s3.amazonaws.com/$folderPrefix
will not work if you are using cloud front. Should be https://$bucket.cloudfront.net/$folderPrefix
. Other that that worked perfect.
crankeye
commented
Jul 6, 2017
Much appreciated. Though the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
soter19
commented
Aug 3, 2017
Well done! It was very useful!!! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
bluemalkin
commented
Aug 7, 2017
Wonderful script which saved my bacon, thank you ! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
diegodurante
Aug 9, 2017
Awesome! It works like a charm!
FYI I had to disable Maintenance Mode to let it works properly ;)
Many many thanks!
diegodurante
commented
Aug 9, 2017
Awesome! It works like a charm! FYI I had to disable Maintenance Mode to let it works properly ;) Many many thanks! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
gregshep
Sep 12, 2017
Perfect! Worked for me too!
I added this bucket policy to my media bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::BUCKETNAMEHERE/*"
}
]
}
Thank you for maintaining this great utility.
gregshep
commented
Sep 12, 2017
Perfect! Worked for me too!
Thank you for maintaining this great utility. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
xgiadmin
Jan 24, 2018
Awesome script! Thank you for providing. Any ideas on how we could we modify this to move from one AWS Bucket to another? Say all files exist in a bucket for development then we want to move those to another AWS bucket for production.
xgiadmin
commented
Jan 24, 2018
Awesome script! Thank you for providing. Any ideas on how we could we modify this to move from one AWS Bucket to another? Say all files exist in a bucket for development then we want to move those to another AWS bucket for production. |
Hi,
Great script. I had a little trouble getting it to work as the
Amazon_S3_And_CloudFront
now seems to need some arguments in the constructor. If you requirewp-content/plugins/amazon-web-services/amazon-web-services.php
and then constructAmazon_Web_Services
first then you can pass that intoAmazon_S3_And_CloudFront
like so:Also i'm using an EU West bucket, you can also then get the bucket region using:
$region = $awsS3->get_setting('region');
And update the attachment meta data update to: