Independent software, built & maintained by PRBLEM.
28 releases 21 free · 7 professional STORE / 2.41.0
PRBLEMindependent software
Home Field Notes PHP
PHP FIELD NOTE

PHP Upload Limits Are More Complicated Than upload_max_filesize

The number shown in php.ini may not be the number a user can successfully upload. The effective limit is the smallest relevant boundary in the whole request path.

PRBLEM — XenForo add-ons, WordPress plugins and software tools FIELD NOTE // 9008

A user tries to upload a 40 MB file. PHP says
upload_max_filesize = 64M.

The upload still fails.

That is not contradictory. upload_max_filesize is only
one boundary in a multi-layer request path.

Think in terms of the
smallest limit

A simplified upload path looks like this:

browser
  -> CDN / proxy
  -> web server
  -> PHP request limits
  -> temporary storage
  -> WordPress/application rules
  -> destination filesystem

If any layer rejects the request, a larger limit later in the path
does not help.

The effective maximum is often the smallest applicable limit.

upload_max_filesize

This PHP directive limits the size of an individual uploaded
file.

Example:

upload_max_filesize = 64M

Useful, but not sufficient.

post_max_size

File uploads are normally part of an HTTP POST request.

If:

upload_max_filesize = 64M
post_max_size = 16M

then a 40 MB upload cannot succeed through that request path.

The entire POST body has a lower ceiling.

A diagnostic should therefore display both and calculate an effective
PHP-side limit conservatively.

Memory is a separate concern

memory_limit is not simply another upload-size
setting.

PHP does not necessarily load every uploaded byte into application
memory at once. However, later processing may use substantial memory—for
example image decoding, resizing, archive extraction or metadata
parsing.

A file can upload successfully and fail during processing because the
operation’s memory footprint is much larger than the compressed file
size.

This distinction matters for large images.

Temporary storage can fail
first

PHP needs temporary storage for incoming uploads.

Problems include:

  • temp directory missing;
  • wrong permissions;
  • full filesystem;
  • restrictive container mount;
  • cleanup or security software interfering.

A configuration screen that only prints maximum sizes will miss this
entire category.

The web server may
impose its own limit

Nginx can reject large request bodies through configuration such as
client_max_body_size.

Apache and hosting platforms can have their own request-size
controls.

A reverse proxy or CDN may also enforce limits before the request
reaches your server.

When PHP never receives the request, changing php.ini
cannot fix the problem.

WordPress reports an
effective limit

WordPress exposes an upload limit based on the environment it can
observe.

That value is useful, but it cannot always know every external
proxy/CDN restriction.

Treat it as application-visible capacity, not an end-to-end
guarantee.

MIME support is another axis

A file can be small enough and still be rejected because the type is
not allowed.

For media, format support also depends on image libraries.

A practical WordPress upload diagnostic can inspect:

  • allowed MIME types;
  • GD availability;
  • Imagick availability;
  • WebP support;
  • AVIF support where applicable;
  • EXIF support if workflows depend on it.

Do not confuse “WordPress recognizes this MIME type” with “the
server’s image library can perform every transformation on it.”

Write permission is not
theoretical

The uploads directory can exist and be readable while not being
writable by PHP.

A safe test is stronger than inspecting mode bits alone.

The application can create a tiny random file through the same
upload-area mechanism, read it, and delete it immediately.

The test should:

  • use unpredictable filename data;
  • contain no executable PHP;
  • create only a few bytes;
  • verify deletion;
  • report failure without leaving garbage behind.

This exercises the operation instead of merely inspecting
configuration.

Disk free space matters

A directory can be writable but effectively unusable because the
filesystem is nearly full.

Uploads, image transformations and ZIP extraction may require
temporary space beyond the final file size.

A health screen should report free space as context, while avoiding
simplistic claims such as “10 GB is always enough.” Workloads
differ.

Timeouts can appear as
upload failures

Large uploads on slow connections can interact with request and proxy
timeouts.

The correct fix is not automatically “increase every timeout.”

First identify where the connection is being terminated:

  • client;
  • CDN;
  • proxy;
  • web server;
  • PHP;
  • application processing stage.

Logs and response status are important here.

A safer troubleshooting
sequence

When uploads fail:

  1. Record the file size and type.
  2. Check the actual HTTP status/error.
  3. Compare upload_max_filesize and
    post_max_size.
  4. Check WordPress’s reported maximum.
  5. Verify temp storage and uploads directory writability.
  6. Check disk space.
  7. Check proxy/web-server limits.
  8. If media processing fails after upload, investigate memory and
    image-library support.
  9. Run a tiny controlled write/read/delete test.

Avoid making the
diagnostic destructive

An upload health tool does not need to change php.ini,
.htaccess, Nginx configuration or file permissions
automatically.

Those changes are hosting-specific and can break a site when guessed
incorrectly.

A better tool says:

PHP upload_max_filesize    64 MB
PHP post_max_size          16 MB
Application visible limit  16 MB
Uploads path writable      yes
Temporary path             available
WebP processing            yes

Now the administrator knows where to act.

The real upload limit is not one number.

It is the result of several independent boundaries—and the smallest
relevant one wins.