Proxying Requests to /wp-content/uploads/ to a Production Site

Getting a database dump from a production site to a local site is pretty easy. But when I’m browsing the local site all of the items in the media library are broken unless I download a copy of the /wp-content/uploads/ directory. Most of the time that can be a really big download and I’m in a hurry. Instead you can proxy requests to the production URL and reference the media items that way. Here is how to do that using the nginx web server:

  1. Go to the root directory of the local install for your site. I install my local sites to the Sites directory in my home directory on my Mac so I would go to ~/Sites/mysite.local.
  2. Go to the /conf/nginx directory
  3. Add a new file called uploads-proxy.conf
  4. Paste the following contents into that file. Be sure to replace https://example.com/wp-content/uploads/ with the URL of the uploads directory on your production site.
location ~ ^/wp-content/uploads/(.*) {
	try_files $uri $uri/ @uploadsproxy;
}

location @uploadsproxy {
	resolver 8.8.8.8; # Use Google for DNS.
        resolver_timeout 60s;
	proxy_http_version 1.1;
	proxy_pass https://example.com/wp-content/uploads/$1$is_args$args;
}
  1. Save uploads-proxy.conf
  2. Open site.conf
  3. Find the following line:
    #
    # WordPress Rules
    #
    include includes/wordpress.conf;
  1. Add the following after that line
    #
    # Proxy requests to the upload directory to the production site
    #
    include uploads-proxy.conf;

your site.conf file should now look like

    #
    # WordPress Rules
    #
    include includes/wordpress.conf;

    #
    # Proxy requests to the upload directory to the production site
    #
    include uploads-proxy.conf;
  1. Save the file and restart your site in the Local/Local by Flywheel control panel
  2. Load your local site in your browser and you should now see images loaded

A couple of notes:

  • nginx will check your local file system for the requested file first. If it finds it it will use that file otherwise it will try and request the file from the production site and serve the file that way.
  • If you upload an image to your local site it will work as expected.
  • Query strings will be passed along to the request to your production uploads folder. That’s what $is_args$args is for in the proxy_pass directive. I.e. with the URL https://mysite.local/wp-content/uploads/2019/11/file.jpg?foo=bar, ?foo=bar will be included with the proxy request.

Thanks to Editing nginx site.conf file for the inspiration.

2 Likes

Exactly the idea that I’m in search of, except the execution isn’t working for me.

Hi Timothy,

I actually found a simpler way to do this using 3 WordPress filters. We can check if the file in the uploads directory exists locally and if it does don’t change anything. But if the file doesn’t exist in the uploads directory then we can replace it with a different URL and serve the media file that way.

Works well for local development without having to download a complete copy of the production site’s uploads directory.

Here it is as a gist: https://gist.github.com/kingkool68/d5e483528a260e5c7921afb5c88bffd6

1 Like

The original version of this didn’t work for me anymore, but I made a few changes and this is working:

  1. Go to the root directory of the local install for your site.
  2. Go to the /conf/nginx directory
  3. Add a new file called uploads-proxy.conf
  4. Paste the following contents into that file. Be sure to replace https://example.com/wp-content/uploads/ with the URL of the uploads directory on your production site.
location ~ ^/wp-content/uploads/(.*) {
    if (!-e $request_filename) {
        rewrite ^/wp-content/uploads/(.*) https://example.com/wp-content/uploads/$1 redirect;
    }
}
  1. Save uploads-proxy.conf
  2. Open site.conf.hbs
  3. Find the following lines:
#
# WordPress Rules
#
{{#unless site.multiSite}}
include includes/wordpress-single.conf;
{{else}}
include includes/wordpress-multi.conf;
{{/unless}}
  1. Add the following after that line:
    #
    # Proxy requests to the upload directory to the production site
    #
    include uploads-proxy.conf;
  1. Save the file and restart your site in the Local/Local by Flywheel control panel.
  2. Load your local site in your browser and you should now see images loaded.
2 Likes

My goto method for this now if using an Apache web server is to drop the following .htacess file in /wp-content/uploads/

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) https://production-url.com/wp-content/uploads/$1 [L]

Apache will check if the requested file is on disk and serve that. If the local file is not found, it will create a rewrite rule for that request pointing to a different URL, like the production site. Works great and is dead simple to implement.

2 Likes

Confirmed that this method works as of Local version 7.1.2+6410 on Linux.

1 Like

Hey everyone, I created a bash script to automate it, take a look and enjoy :slight_smile:

1 Like

Hi,
It isn’t working for my WP ( multisite )

Hi @kingkool68 this is working just fine on my local installation. Thank you!

1 Like