Moving WordPress’ /wp-content/uploads out of your DocumentRoot
Why might you want to move your /wp-content/uploads
folder out of your DocumentRoot? In my case, I use DropBox to sync files between my desktop and my laptop for doing development – no matter where I was working last, my changes, including Subversion status from the hidden .svn
directories, are ready to go on the other computer (assuming I have Internet access of course, but even then DropBox will copy over the local network if it’s available, which means it’s pretty quick at home). For some of my site’s, like this one, there are gigabytes and gigabytes of images in my uploads directory, but they don’t really do that much for me in terms of development, but I still need them.
The solution for me was to move the uploads folder outside of the Apache DocumentRoot
, were it can still be accessed, but doesn’t count against my DropBox usage (and doesn’t suck up bandwidth syncing thumbnail generation and the like.)
My first order of business was to break uploads out into a different SVN path – otherwise it will just update the folder every time you run an “svn up
“. On the production server, you would want to do the following:
# WordPress Files # https://svn.example.com/mysite/web/trunk svn co https://svn.example.com/mysite/web/trunk /var/www/mysite/html # WordPress Uploads # https://svn.example.com/mysite/uploads/trunk svn co https://svn.example.com/mysite/uploads/trunk /var/www/mysite/html/wp-content/uploads # add "uploads" to your svn:ignore in the wp-content folder svn propedit svn:ignore /var/www/mysite/html/wp-content/ svn up /var/www/mysite/html/wp-content/ svn commit -m "saving svn:ignore for uploads" /var/www/mysite/html/wp-content/
And then on your Workstation, the following:
# WordPress Files # https://svn.example.com/mysite/web/trunk svn co https://svn.example.com/mysite/web/trunk ~/Dropbox/MySites/mysite # WordPress Uploads # https://svn.example.com/mysite/uploads/trunk svn co https://svn.example.com/mysite/uploads/trunk ~/Documents/MySites/mysite
I also added the following rules to /etc/subversion/config
on my server and ~/.subversion/config
on my workstation to prevent thumbnails from being added – there are lots of ways these can be regenerated if necessary.
[miscellany] global-ignores = *-[0-9]*x[0-9]*.jpg -[0-9]*x[0-9]*.gif -[0-9]*x[0-9]*.png -[0-9]*x[0-9]*.bmp -[0-9]*x[0-9]*.jpeg
Now in your Apache configuration for your workstation, you need to set an AliasMatch
for the uploads directory so that Apache can serve up these files. I use MAMP running as my user, so I don’t have to worry about permissions, but you should keep this in mind depending on your configuration.
<VirtualHost *:80> DocumentRoot "/Users/justinsilver/Dropbox/MySites/mysite" ServerName local.mysite.com # Reference the uploads folder in your Documents AliasMatch ^/wp-content/uploads/(.*) /Users/justinsilver/Documents/MySites/mysite/wp-content/uploads/$1 <Directory /Users/justinsilver/Dropbox/MySites/mysite> AllowOverride All </Directory> </VirtualHost>
With all of this done, you’re good to go as far as serving files, but WordPress will still be confused when it tries to write to the directory, since it uses an absolute path. To fix this, we can use a static defined in wp-config.php
(which should be different than production anyway, considering you probably had to set overrides for WP_HOME
and WP_SITEURL
plus the local database configuration) and use that to selectively change the path to the uploads directory. Thus, add the absolute path to your wp-config.php like so, on the workstation:
define('WP_DEV_UPLOADS', '/Users/justinsilver/Documents/MySites/mysite/wp-content/uploads');
With this set, add the following to your theme’s functions.php, or your functions plugin (more on this at a different time) to hook to the “upload_dir” and change the uploads directory that WordPress uses.
if (defined('WP_DEV_UPLOADS')){ if (is_dir(WP_DEV_UPLOADS)){ // use directory outside of Dropbox for uploads so they dont go to Dropbox (uses Alias in VirtualHost) function wp_dev_upload_dir($upload_dir){ $upload_dir['path'] = str_replace( $upload_dir['basedir'], WP_DEV_UPLOADS, $upload_dir['path'] ); $upload_dir['basedir'] = WP_DEV_UPLOADS; return $upload_dir; } add_filter('upload_dir', 'wp_dev_upload_dir'); } else { error_log('WP_DEV_UPLOADS is defined but does not exist: ' . WP_DEV_UPLOADS); } }
This is great!
Is there a way to also make this method work on a WordPress multisite installation?
I’ve tried to do it and it does not work quite right.
thanks
Hi Xavier – I haven’t set this up for multisite, but here is some more info that might be helpful https://wordpress.org/support/topic/multisite-upload-dir-change/. Good luck!
Great! But I have one question: when i upload a filde i can find it on my website but i can’t open it because the permalink is the old one …/uploads/…
How I can change this?
Many Thanks!
Hi Andy, if these are existing pages/posts and media then you might need to update the actual post content with the new URL. You can do this with a script, or do it dynamically with filters and a bit more effort. Good luck!
Greetings! Very useful advice in this particular post! It is the little changes that make the greatest changes.
Thanks for sharing!