
About half of the business at Cap Web Solutions is website support and website enhancements. The rest is new development.
Skip the dialog & go to the code.
Website support and care is rather straightforward, but what about the case of an enhancement, where a completely new feature is being added? That project is almost always handled in my local development environment. The problem comes when trying to duplicate the production environment locally. Generally, copying the files down via FTP or SFTP, while not exciting, time efficient, or even remotely interesting, can be accomplished. Good time to kick it off and go brew a fresh pot of coffee.
However, I draw the line at copying the uploads folder tree! Waiting for 1000’s of jpg’s and png’s to download is … just … wrong. Plain and simple.
The problem is, though, is that when I try to look at the local version of the website, I really don’t like to look at a bunch of little boxes on the screen where an image should be. It feels like it is just screaming “You lazy bum. If you had copied me down, you wouldn’t have to look at this annoying little box telling you the image is missing.” I realize it’s not actually doing that, but the circus in my head is telling me it is.
There has to be a better way. Thank you Google, stackexchange.com, and the local WordPress meetup.
After a few, well, more than a few, attempts, I did come up with a solution that works for me. My solution allows me to duplicate the production website on my local development environment (Desktopserver from ServerPress running on my hand-built 64-bit Windows 10 beast) but without the uploads directory and not see any of those little “image not found” gremlins.

“How”, you might ask, “does one easily accomplish this?” HTACCESS is the rescue. Sort of like HGTV’s ‘George to the Rescue’, but without the goofy smile.
The htaccess file enables you to control the Apache web server used by Desktopserver. With it, you can redirect any request for an image file on the local Desktopserver development environment to the corresponding real live file on the production website.
Cool huh? And with little to no performance degradation. Gone are the days of making sure I copied every last one of those pesky pictures to my local machine, consuming my valuable disk space.
Enough already. Show me how.
Herewith, then, is the solution I use, along with a description of what is going on.
The code below is copied and pasted into the .htaccess file in the root of your development website. When you create a new development website with Desktopserver, a default .htaccess file is created for you. This code should go at the top of that file, before any other directives.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
A couple of assumptions here:
- local development websites are stored as sub-directories under c:/windows/projects
- local development website is named website.dev
- local development website uploads found in the standard WP install location in wp-content
- production website can be found at http://website.com
- production uploads folder tree stuff is in the standard WordPress install location
Let’s get to it.
Line 1 is a single line comment. Anything after the # is ignored by Apache.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
Lines 2 & 8 are the two commands that make up a conditional statement. It checks to to make sure that the URL rewrite engine app (mod_rewrite.c) is found and is running on your desktop Apache server. If TRUE, then do all the commands up to the /IfModule command. If it’s not true, then skip everything in between. If this is the case, this whole post is for naught.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
Line 3 is a command to make sure that the URL re-writing rules engine is turned on. Gotta be there. Starting your Desktopserver will turn this on, but its a good habit to use it.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
Line 4 is the command that sets the base of the relative path structure being used. In our example the .htaccess file is found in c:/windows/projects/website.dev, for example. The “/” is telling us that the relative base for all our local URL redirects is “c:/windows/projects/website.dev”. If Apache is trying to find /wp-content/uploads/mybigpic.jpg this directive is telling it to actually use the Windows file path of “c:/windows/projects/website.dev/wp-content/uploads/mybigpic.jpg “.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
Line 5 is a rewrite rule condition directive. It is testing to see if the file being processed, represented by the full local filesystem pathname {REQUEST_FILENAME}, does not exist. The “!” negates the “-f” parameter which test if the file exists.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
Line 6 is a rewrite rule condition directive, too. HTTP_HOST refers to the HOSTNAME of the production document. Think the same HOSTNAME as you might specify when connecting to your website with an FTP client. In our case, we are going to replace that part of the local filesystem filename with the appropriate production filesystem path. Locally the HOSTNAME under our Desktopserver is “127.0.0.1”. This directive will replace the “c:/windows/projects/website.dev/” part of the mybigpic.jpg file path with “http://website.com/” so that the production image file is referenced in place of the local system file (which does NOT exist). Note that the “^” is part of a regular expression (REGEX) that matches anything from the beginning of the line up to the alpha characters “website”. The “” is used to escape the “.” in the file path and pass it along as the period character rather than as a special indicator to the Apache interpreter. The “$” at the end is another REGEX match character that tells the interpreter to match anything from here to the end of the line.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
And finally, line 7 is the directive that actually does the replacement in path of the local file so that the production file is used. Every referenced file with a pathname that has the pattern “wp-content/uploads/” in the middle of it, has the beginning of the file path up through the pattern, replaced with “http://website.com/wp-content/uploads/”. The rest of the file path is the same and is attached to the end. The local WordPress install can safely reference the production media file.
# Load media files from production server if they don't exist locally <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{HTTP_HOST} ^website.dev$ RewriteRule ^wp-content/uploads/(.*)$ http://website.com/wp-content/uploads/$1 [NC,L] </IfModule>
That’s about it. If you break it down, its not so alarming.
When I create a new local development website that is a copy of a Production site, I add these directives into the .htaccess file that Desktopserver creates. I make change to Line 6 and replace website.dev with mynewdevsite.dev. I always create my local development sites with a “.dev” suffix. If you use “.com” or anything else, you will need to replace “.dev$” with your suffix.
Thanks for getting all the way through this.
Feel free to offer your solutions on how you deal with this or add your own comments on my approach.