Skip to content

Instantly share code, notes, and snippets.

@kingkool68
Last active March 24, 2024 11:37
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save kingkool68/d5e483528a260e5c7921afb5c88bffd6 to your computer and use it in GitHub Desktop.
Save kingkool68/d5e483528a260e5c7921afb5c88bffd6 to your computer and use it in GitHub Desktop.
Check if a local file exists in the WordPress media library and if it doesn't exist, replace the URL with a different URL. Helpful when working with a local site that doesn't have all of the media downloaded as the production site. See https://localwp.com/community/t/proxying-requests-to-wp-content-uploads-to-a-production-site/15701
<?php
// Put this in wp-config.php and replace https://example.com/ with the URL of the production site.
define( 'RH_USE_REMOTE_MEDIA_URL', 'https://example.com/' );
// Put the rest of this in functions.php or a custom plugin or somewhere else.
if ( defined( 'RH_USE_REMOTE_MEDIA_URL' ) && ! empty( RH_USE_REMOTE_MEDIA_URL ) ) {
add_filter( 'wp_get_attachment_image_src', 'filter_wp_get_attachment_image_src' );
add_filter( 'wp_calculate_image_srcset', 'filter_wp_calculate_image_srcset' );
add_filter( 'wp_get_attachment_url', 'filter_wp_get_attachment_url' );
}
function filter_wp_get_attachment_image_src( $image = array() ) {
if ( ! is_array( $image ) || empty( $image ) ) {
return $image;
}
$wp_upload_dir = wp_upload_dir();
$base_dir = $wp_upload_dir['basedir'];
$base_url = $wp_upload_dir['baseurl'];
$absolute_path = str_replace( $base_url, $base_dir, $image[0] );
if ( file_exists( $absolute_path ) ) {
return $image;
}
$find = get_site_url();
$replace = RH_USE_REMOTE_MEDIA_URL;
$image[0] = str_replace( $find, $replace, $image[0] );
return $image;
}
function filter_wp_calculate_image_srcset( $src = array() ) {
if ( is_array( $src ) && ! is_admin() ) {
$wp_upload_dir = wp_upload_dir();
$base_dir = $wp_upload_dir['basedir'];
$base_url = $wp_upload_dir['baseurl'];
$find = get_site_url();
$replace = RH_USE_REMOTE_MEDIA_URL;
foreach ( $src as $key => $val ) {
$absolute_path = str_replace( $base_url, $base_dir, $val['url'] );
if ( ! file_exists( $absolute_path ) ) {
$val['url'] = str_replace( $find, $replace, $val['url'] );
$src[ $key ] = $val;
}
}
}
return $src;
}
function filter_wp_get_attachment_url( $url = '' ) {
if ( is_admin() ) {
return $url;
}
$wp_upload_dir = wp_upload_dir();
$base_dir = $wp_upload_dir['basedir'];
$base_url = $wp_upload_dir['baseurl'];
$find = get_site_url();
$replace = RH_USE_REMOTE_MEDIA_URL;
$absolute_path = str_replace( $base_url, $base_dir, $url );
if ( ! file_exists( $absolute_path ) ) {
$url = str_replace( $find, $replace, $url );
}
return $url;
}
@pixelbrad
Copy link

pixelbrad commented May 12, 2020

Just a heads up, I tried this on a local project and ran into a fatal error. On lines 7, 8, and 9, you're adding filters as if the functions are part of a class.

if ( defined( 'RH_USE_REMOTE_MEDIA_URL' ) && ! empty( RH_USE_REMOTE_MEDIA_URL ) ) {
	add_filter( 'wp_get_attachment_image_src', array( $this, 'filter_wp_get_attachment_image_src' ) );
	add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_wp_calculate_image_srcset' ) );
	add_filter( 'wp_get_attachment_url', array( $this, 'filter_wp_get_attachment_url' ) );
}

should be

if ( defined( 'RH_USE_REMOTE_MEDIA_URL' ) && ! empty( RH_USE_REMOTE_MEDIA_URL ) ) {
	add_filter( 'wp_get_attachment_image_src', 'filter_wp_get_attachment_image_src' );
	add_filter( 'wp_calculate_image_srcset', 'filter_wp_calculate_image_srcset' );
	add_filter( 'wp_get_attachment_url', 'filter_wp_get_attachment_url' );
}

Other than that, this script is a godsend. Thank you for sharing this with the rest of us.

@kingkool68
Copy link
Author

@pixelbrad Oops! You're right. I have updated the gist.

@KimBranzell
Copy link

Just a heads up, you missed the last $this in line 9, which was still causing a fatal error

@kingkool68
Copy link
Author

@KimBranzell Oops! You're right. I have updated the gist.

@bacoords
Copy link

Thanks! This worked for me but I had to remove the trailing slash when defining RH_USE_REMOTE_MEDIA_URL. Not sure if that's specific to my environment but it may help others.

@timnolte
Copy link

timnolte commented Aug 16, 2022

@bacoords if you have a Composer based site setup I took this work and created a MU Plugin that can be installed as a dev dependency on a site. I have addressed that trailing slash issue in my version of the code.

https://packagist.org/packages/ndigitals/wp-local-media-proxy

@kingkool68
Copy link
Author

Also if you're running WordPress on an Apache server you can accomplish the same thing by dropping a .htaccess file into /wp-content/uploads/ with the following contents:

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

Replace https://example.com with the production URL of your site to redirect media requests to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment