Many types of sites have a directory for user-uploaded content. Graphics related to posted articles, or avatar images for users, etc. Securing these can be very tricky. We recommend dividing this process into two steps.
First step: Your code should limit what types of files to upload. For example, if you are uploading forum avatars, it might be appropriate to allow jpg, png, and gif files. If you are working on a project team website for school, you might be uploading a lot of .pptx or .pdf files.
Watch out for multiple file extensions! It's not enough to just check if the file has ".jpg" in it, because it might be named "exploit.jpg.php" or "exploit.php.jpg." Apache parses file extensions individually, so both of those examples will be executed as PHP. (Although exploit files are only rarely so helpful as to have "exploit" in the name!)
If you're using application software, like WordPress, it may take care of this first step for you. If not, you'll have to code it yourself. Here is a PHP starting point. (And here is the unit test for that starting point.)
Second step: You should place an .htaccess file in any web-writeable directory that will prevent execution of files that slip past or that get onto the site through some other vulnerability. Create or add to that directory's .htaccess file with something like this:
<FilesMatch "\.(cgi|php|pl|py|rb)">
Require all denied
</FilesMatch>
This is hardly infallible, but will foil many hacking attempts, and should be included in any directory that contains uploaded or cached content. Depending on your site, you may want to add html, js, and css to the list of prohibited extensions.
To reverse this restriction for a subdirectory (rarely needed and even more rarely a good idea), create or add to that subdirectory's .htaccess file with content like:
<FilesMatch "\.php">
Require all granted
</FilesMatch>
In the case of adding blocking execution in a directory, always block everything. In the case of re-allowing execution in a subdirectory, allow only the specific type of execution you need. The above example re-allows PHP.
These steps cannot guarantee that your site's upload directory can't be exploited, but they will protect it from most of the generic bulk attacks that are designed to exploit known vulnerabilities on sites with a default configuration.