Skip to main content

Files, Uploads, Streams, and JSON

Basic File Functions

file_exists($path);
is_readable($path);
is_writable($path);
file_get_contents($path);
file_put_contents($path, $contents);
unlink($path);

Use carefully in WordPress. Prefer WordPress APIs when working with uploads, media, and plugin paths.

Paths and URLs

$plugin_file = plugin_dir_path(__FILE__) . 'includes/file.php';
$theme_file = get_stylesheet_directory() . '/template-parts/card.php';
NeedUse
Filesystem pathplugin_dir_path(), get_stylesheet_directory()
Browser URLplugin_dir_url(), get_stylesheet_directory_uri()

Never build paths directly from unsanitized user input.

Upload Directory

$uploads = wp_upload_dir();

$base_dir = $uploads['basedir'];
$base_url = $uploads['baseurl'];

Check for errors.

if (! empty($uploads['error'])) {
error_log($uploads['error']);
}

Sanitize File Names

$filename = sanitize_file_name($raw_filename);

Attachments

echo wp_get_attachment_image($image_id, 'large', false, [
'class' => 'hero-image',
]);

Store attachment IDs instead of raw URLs when possible.

Upload Handling

For normal media workflows, use WordPress media APIs.

require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';

JSON Encode and Decode

$json = wp_json_encode($data);
$data = json_decode($json, true);

if (! is_array($data)) {
return [];
}

Validate decoded shape before using it.

Sending JSON Response

wp_send_json_success([
'items' => $items,
]);
wp_send_json_error([
'message' => __('Invalid request.', 'my-plugin'),
], 400);

CSV

$handle = fopen($path, 'r');

while (($row = fgetcsv($handle)) !== false) {
// Process row.
}

fclose($handle);

Validate row shape and sanitize values before storage.

Common File Pitfalls

  • Treating upload filenames as safe paths.
  • Allowing arbitrary file extensions.
  • Writing outside uploads or plugin-controlled directories.
  • Deleting files based on raw request parameters.
  • Storing only media URLs instead of attachment IDs.
  • Decoding JSON and assuming the expected keys exist.
  • Echoing file contents without escaping or content-type checks.