Working with uploaded files
On most platforms, media files uploaded to a WordPress site are stored in a filesystem local to the site’s web server. On the VIP Platform, media files uploaded or imported to a WordPress environment are stored on the VIP File System, which is an external object store. A WordPress site’s /wp-content/uploads/
directory is mapped to this external object store. This design provides better security and allows VIP’s CDN to more easily scale access to a site’s media.
The VIP File System is read-only but several different methods exist to programmatically access and interact with media files stored on the VIP File System.
Limitations
- Because the VIP File System uses an object store, it lacks a true directory structure.
- Communication with the VIP File System occurs over HTTP. At a minimum, every filesystem-related operation takes 200 milliseconds to process. As a result, file operations such as
file_exists()
andfile_get_contents()
should be used at a minimum to prevent a negative impact to page load time. - Media can only be uploaded to a path within
/uploads/
. Only paths to files that begin with/wp-content/uploads/
are possible; other paths will not work. - Permissions-related operations (e.g.,
chmod()
,chown()
) will not work as expected and should not be used. - The system
/tmp
directory should be used to perform operations on temporary files and other local file operations such as extracting and working with ZIP files. - Some themes and plugins expect to have write permissions, or that media files are stored locally, and may not work as expected with the VIP File System.
- All file names are treated as case-insensitive.
- A limit of 2000 modifications are permitted for overwriting and versioning any particular file path.
PHP Stream Wrapper
A custom PHP Stream Wrapper has been integrated into the VIP File System to allow for more complex interactions. This allows most filesystem functions (e.g. fopen()
, fwrite()
, file_put_contents()
) to automatically work with media uploads within the /wp-content/uploads/
path. Most open, read, and write file-related operations are supported by the PHP Stream Wrapper, including copy()
, rename()
, and unlink()
.
Because the VIP File System uses an object store, it lacks a true directory structure. As a result:
- Most operations on directories will not work as expected.
- Directory traversal operations will not work because there are technically no true directories to traverse.
- Some directory-related operations like
mkdir()
will returntrue
because directories are automatically created by the Filesystem API. - PHP directory functions such as
rmdir()
will not work as expected. scandir()
,list_files()
,glob()
, andopendir()
will not work as expected, and will instead return either an empty array orfalse
and trigger a PHP Warning.is_dir()
will not work as expected if it is called against a file lacking an extension; it will returntrue
.- Because directories are created automatically, it is not necessary to add logic in code to check if a directory exists. If
file_exists()
is used in code to check if a directory exists, it will always returntrue
for paths within/wp-content/uploads/
.
WordPress filesystem functions
To generate correct, writeable paths use the WordPress function wp_get_upload_dir()
or wp_upload_dir()
. Hard-coding a path like /wp-content/uploads/...
will not work.
For simple file uploads use media_handle_sideload()
, media_sideload_image()
, or wp_upload_bits()
.
WP_Filesystem API
To use the WP_Filesystem API, the following code must be added to a site’s codebase usually within the /themes
directory, /plugins
directory, or /client-mu-plugins
directory:
global $wp_filesystem;
if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ) {
$creds = request_filesystem_credentials( site_url() );
wp_filesystem( $creds );
}
Note
Because the VIP File System lacks a true directory structure, most WP_Filesystem operations related to directories will not work as expected.
Code examples
In this code example, a file is uploaded to /uploads/csv/
:
$csv_content = '1,hello,admin';
$upload_dir = wp_get_upload_dir()['basedir'];
$file_path = $upload_dir . '/csv/updated.csv';
file_put_contents( $file_path, $csv_content );
// The file will now be accessible at https://example-com.go-vip.net/wp-content/uploads/csv/updated.csv
In this code example, a file is uploaded to /uploads/csv/
using the WP_Filesystem API:
$csv_content = '1,hello,admin';
$upload_dir = wp_get_upload_dir()['basedir'];
$file_path = $upload_dir . '/csv/updated.csv';
global $wp_filesystem;
if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ) {
$creds = request_filesystem_credentials( site_url() );
wp_filesystem( $creds );
}
$wp_filesystem->put_contents(
$file_path,
$csv_content
);
In this code example, a CSV file that was previously uploaded to WordPress is retrieved, parsed, and stored in a variable:
$csv_attachment = get_attached_file( 1234 );
$csv_file = file( $csv_attachment );
$csv_content = array_map( 'str_getcsv', $csv_file );
Last updated: February 09, 2024