Programmatically Upload Files in WordPress (and Create Associated Meta Data)

This is post one of two on how to upload files in WordPress and created associated meta data.

In a recent project, I’ve been working on a plugin in which the user needs to upload a file to a custom post type by using an input element (of type file , obviously) rather than using the WordPress media uploader.

In addition to being able to upload the file, the user must also be able to view the file and remove the file (via Ajax) by an available anchor.

In order to do this, the plugin has to do the following:

Upload the file to the `uploads` directory Save the file URL to the custom post type’s post meta data Save the file path to the custom post type’s post meta data Delete the file from the `uploads directory Clear the post meta data referencing the file

The primary reason that you have to store the file’s location on disk is because you can’t rely on PHP to delete a file via remote requests.

To that end, you need to be able to store not only where the file is on disk (for the sake of being able to delete), but also the URL of the file so that visitors or viewers can access the file via their browser.

Over the next two articles, I’ll share how to programmatically upload files in WordPress and save their associated meta data, and then I’ll share how to programmatically delete the files in WordPress as well as their associated meta data.



Programmatically Upload Files in WordPress

Note that I mentioned that we are not using the WordPress media uploader to do this; however, we need to be able to store the files in the `uploads` directory that exists in the users WordPress installation.

1. Define The Markup

This is where the `wp_upload_bits` function comes into play. But before we take a look at that code, we need some basic markup that allows the user to upload a file:

This snippet is obviously part of a larger display within the plugin, but it should be easy enough to follow. The most important thing is that you recognize the`input` element’s `name` attribute, and that you properly setup your nonce value.

Next, you need to setup the code for uploading the file. Before actually doing any uploading, you need to make sure that files are actually set for upload, and, if so, that the user has permission and the proper nonce values are being sent across the wire for the given file.

To do this, I normally setup the following conditional:

As well as these helper functions:

Assuming both of these evaluate to `TRUE`, then I can actually upload the file. And this is where `wp_upload_bits` comes into play.

Here’s what the full code looks like:

At this point, we’re successfully saving the file to the most recent subdirectory of the `uploads` directory.

Granted, this particular block of code could include a bit more error checking, the reduction of muting of `file_get_contents` warnings, as well as replacing `file_get_contents` with `wp_remote_get`, but the example above – for all intents and purposes – serves its purpose in demonstrating how to do this, and covering each of the other additions would add unnecessary length to this [already lengthy] article.

Of course, now we need to associate the uploaded file with the custom post type (or even just the basic post or page, if that’s what you’re working with).

2. Save The File Meta Data

Of course, before you set any meta data, you want to make sure that the upload was successful. To do this, you can setup the following conditional:

How you opt to handle the case when it fails is up to you.

Next, we need to check to see if existing post meta data exists for the post because a user could be upload a file in place of another file. If that’s the case, we don’t want to leave residual files cluttering the `uploads` directory.

To that end, we need a unique meta key that we can use for the post meta API. In my case, I’m simply using `attached-file-url` and `attached-file-path` – one piece of meta data will be the URL to the file, the other, obviously, is the path to the file on the disk.

If a file already exists, then I need to remove it. To do this, I first check the post’s meta data. If something exists for the given meta key, then I’ll delete the file.

Next, I’ll update the post’s meta data with the URL to the file as well as the path to the file.

Now at this point, if you’re to look in the `uploads` directory, you’ll see the file that you uploaded:

And if you take a peek at the database, you’ll see the post meta data associated with the given post:

What About Deleting The Files?

Obviously, deleting the files is the next step in the process.

Doing this is obviously more than a matter of removing the file from the file system – it’s also removing the information from the post meta data in the database, and updating the interface to reflect this change.

In the last post in the series, I’ll cover how to do that.