I was having a problem where WordPress uploads were not loading on my production server. Upon examination, the files were created in the uploads directory but the permissions were not set for the IIS_IUSRS user. This was causing a 500 Internal server error when the images were loaded in the browser.
It turns out that PHP writes files to a temporary directory before moving them to the WordPress uploads folder. This location is set in php.ini under the key “upload_tmp_dir” and defaults to the Windows temp directory (C:WindowsTemp). When files are created here, they are copied to the WordPress uploads directory with the permissions from the temp directory. To solve the issue, change the directory to one the IIS_IUSRS has read access to, or grant IIS_IUSRS read access to the windows temp directory.