PHP File Upload, Image Path and move_uploaded_file Debugger

Free PHP Upload Debugging Tool

PHP File Upload, Image Path and move_uploaded_file Debugger

Find whether your PHP upload problem is caused by the HTML form, $_FILES, PHP limits, an upload error code, the temporary file, destination directory, permissions, filename, MIME validation, database path or browser image URL.

Use this tool when: $_FILES is empty, move_uploaded_file() returns false, an uploaded file never reaches the folder, a filename saves in MySQL but the image is broken, uploads work in XAMPP but fail on hosting, or editing a record accidentally removes the previous image.

$_FILES multipart/form-data move_uploaded_file() Upload error codes MIME validation Image paths Multiple files XAMPP

Describe Your Upload Problem

Complete the fields you know. Optional code and error details improve the diagnosis.

Browser-only analysis: this page does not upload your selected file or execute your PHP. Remove passwords, database credentials, private paths, personal records and secret keys from pasted code.

1. Environment and main symptom

2. HTML form and $_FILES mapping

3. PHP upload status and limits

4. Destination folder and stored path

5. Validation and filename handling

6. Optional sanitized code and error details

Personalized Upload Diagnosis

Likely upload failure

Diagnostic confidence 0%
This is a rule-based estimate. Confirm each result using the real request, $_FILES structure, upload error code, PHP configuration, filesystem and database record.

Most Likely Root Causes

    Fix in This Order

      Form and $_FILES Checks

        Path, Folder and Database Checks

          Detected Upload Error

          Stage-by-Stage Test Matrix

          Upload stage Assessment Exact test

          Personalized Secure Upload Templates

          These examples are starting templates. Match the allowed file types, database connection, authorization rules, CSRF protection, storage folder and public URL to the real project.

          Correct HTML upload form
          Secure single-file upload with database save
          Secure image upload validation
          Multiple-file upload loop
          Edit and safely replace an existing image

          Security and Data-Safety Warnings

            Upload Test Cases

              Viva-Ready Explanation

              Copyable Debugging Report

              How a PHP File Upload Actually Works

              A PHP upload moves through several separate stages. The browser first builds a multipart POST request. The web server and PHP compare the request with configured size and upload limits. PHP writes an accepted upload to a temporary location and creates an entry in $_FILES. Your application then validates the upload, creates a safe destination filename, moves the temporary file and saves a portable value in the database.

              A visible “upload failed” message does not identify which stage failed. The form may never have sent a multipart request. PHP may have rejected the request before your script received it. The temporary file may exist while the destination directory does not. The move may succeed while the database insert fails. The database may contain the correct filename while the HTML uses a server path that a browser cannot open.

              Stage 1: Browser form

              The form must use POST and enctype="multipart/form-data". The file input must have a name that matches the PHP $_FILES key.

              Stage 2: PHP request limits

              PHP checks settings such as file_uploads, upload_max_filesize, post_max_size and the temporary upload directory.

              Stage 3: Temporary upload

              A successful request receives a temporary filename. Your script must process and move the file during the request.

              Stage 4: Validation

              Validate the upload error, size and file contents. Do not trust the original filename or browser-provided MIME type as final proof.

              Stage 5: Permanent storage

              Generate a collision-resistant filename and move the temporary file into a controlled directory outside executable code where possible.

              Stage 6: Database and display

              Save a portable filename or relative path. Build the browser URL separately from the server filesystem path.

              What PHP Stores in $_FILES

              A single file input named profile_image normally produces an array with the original client filename, temporary server filename, upload error code, reported size and browser-supplied type.

              $_FILES["profile_image"]["name"]
              $_FILES["profile_image"]["tmp_name"]
              $_FILES["profile_image"]["error"]
              $_FILES["profile_image"]["size"]
              $_FILES["profile_image"]["type"]

              Your code should inspect error before using tmp_name. An error code other than UPLOAD_ERR_OK means the application should stop and handle that specific condition.

              Code PHP constant Meaning First check
              0 UPLOAD_ERR_OK PHP accepted the upload. Continue with size, content and destination validation.
              1 UPLOAD_ERR_INI_SIZE The file exceeds upload_max_filesize. Check the active PHP configuration and restart the relevant server after changes.
              2 UPLOAD_ERR_FORM_SIZE The file exceeds the form’s MAX_FILE_SIZE value. Review both the form limit and server-side validation.
              3 UPLOAD_ERR_PARTIAL The file was only partly uploaded. Retry and investigate network, proxy or server interruption.
              4 UPLOAD_ERR_NO_FILE No file was selected or received. Check whether the field is optional and whether the user selected a file.
              6 UPLOAD_ERR_NO_TMP_DIR PHP cannot use a temporary upload directory. Check PHP and server temporary-directory configuration.
              7 UPLOAD_ERR_CANT_WRITE PHP failed to write the upload to disk. Check disk space, temporary storage and server permissions.
              8 UPLOAD_ERR_EXTENSION A PHP extension stopped the upload. Check hosting logs and installed upload/security extensions.

              Why $_FILES Can Be Completely Empty

              A missing file key and a completely empty $_FILES array are not always the same failure. A missing key can come from a form name mismatch. A completely empty request may mean the browser did not send multipart data or PHP rejected the entire request before normal form processing.

              Check these conditions in order:

              1. The form uses method="post".
              2. The form includes enctype="multipart/form-data".
              3. The file input has a valid name attribute.
              4. The input is not disabled.
              5. The PHP key exactly matches the input name.
              6. file_uploads is enabled.
              7. The entire request does not exceed post_max_size.

              When the total request exceeds post_max_size, the application may receive empty $_POST and $_FILES arrays. In that situation, checking only $_FILES["field"]["error"] cannot help because the file entry was never created.

              Filesystem Path Versus Browser URL

              PHP and the browser use two different address systems. PHP moves the file using a server filesystem path. HTML displays the file using a public URL.

              Filesystem destination used by PHP

              C:\xampp\htdocs\student-project\uploads\photo.jpg
              
              /var/www/html/student-project/uploads/photo.jpg

              Public URL used by the browser

              http://localhost/student-project/uploads/photo.jpg
              
              https://example.com/uploads/photo.jpg

              A Windows path placed directly in an image src attribute will not become a normal website URL. A portable application commonly stores photo.jpg or uploads/photo.jpg in the database, then builds the server path and public URL separately.

              $filesystemPath = __DIR__ . "/uploads/" . $filename;
              $publicUrl = "uploads/" . rawurlencode($filename);

              Why move_uploaded_file() Returns False

              The function expects a temporary source that PHP recognizes as a file uploaded through HTTP POST. It also needs a valid destination path that the server can write.

              Before moving, confirm:

              • The upload error code equals UPLOAD_ERR_OK.
              • tmp_name is not empty.
              • is_uploaded_file($tmpName) returns true.
              • The destination directory exists.
              • The destination directory is writable.
              • The generated filename contains no path traversal.
              • The destination path uses the correct project directory.
              • The destination does not unintentionally overwrite another file.

              Do not pass the original client filename directly into a destination path without controlling it. Generate the stored filename on the server and use only an approved extension.

              Do Not Validate Uploads Using Only the Extension

              A filename ending in .jpg does not prove that its contents are a JPEG image. The original name and browser-reported type come from the client and can be misleading.

              For general files, Fileinfo can inspect the temporary file and return a detected MIME type. For images, combine a MIME allowlist with an image inspection function such as getimagesize(). Then map the detected MIME type to an extension selected by the server.

              $allowed = [
                  "image/jpeg" => "jpg",
                  "image/png"  => "png",
                  "image/webp" => "webp"
              ];
              
              $finfo = new finfo(FILEINFO_MIME_TYPE);
              $mime = $finfo->file($tmpName);
              
              if (!isset($allowed[$mime])) {
                  exit("Unsupported image type.");
              }
              
              $imageInfo = getimagesize($tmpName);
              
              if ($imageInfo === false) {
                  exit("The uploaded file is not a readable image.");
              }

              Validation should reflect the project’s real needs. A profile-image feature should not accept arbitrary executable or archive files merely because the upload folder exists.

              Use Server-Generated Filenames

              Original filenames can contain spaces, unusual Unicode characters, repeated names or path-like content. Saving every image under a fixed name also causes each new upload to overwrite the previous one.

              A collision-resistant filename can be generated like this:

              $filename = bin2hex(random_bytes(16)) . "." . $extension;

              Store the original filename separately only when the application needs to show it to the user. Do not use the original name as proof of type or as the permanent storage path.

              Coordinate the File Move and Database Save

              The filesystem and MySQL do not automatically share one transaction. This creates two possible inconsistencies:

              • The database contains a filename but the file move failed.
              • The file exists but the database insert or update failed.

              A safer sequence is:

              1. Validate the request and upload error.
              2. Inspect file contents and size.
              3. Generate a safe destination filename.
              4. Move the file successfully.
              5. Save the confirmed filename inside a database transaction.
              6. If the database operation fails, remove the newly moved file.

              When replacing an existing image, keep the old file until the new file has moved and the database update has committed. Delete the previous file only after the record points to the new file.

              Multiple-File Uploads

              A multiple-file input should use both the attribute and array-style name:

              PHP then stores arrays under each file property. Your code must loop through the matching indexes of name, tmp_name, error and size.

              The PHP max_file_uploads setting may also limit how many files one request accepts. Application limits should be lower when the project does not need large batches.

              Upload Works in XAMPP but Fails on Hosting

              A local Windows project and a hosted Linux server may behave differently even when the same PHP file is uploaded.

              • Hosting upload and POST limits may be lower.
              • The destination folder may not be writable by the web-server user.
              • Linux filenames are usually case-sensitive.
              • The document root and filesystem layout may be different.
              • open_basedir may restrict accessible directories.
              • Fileinfo or image extensions may differ.
              • Temporary storage may be full or unavailable.
              • A hosting security rule may reject specific types or request sizes.

              Use __DIR__ to anchor server paths to the current PHP file rather than assuming the process always runs from the same working directory.

              Safe Upload Debugging Order

              1. Confirm the request uses POST and multipart encoding.
              2. Compare the input name with the exact $_FILES key.
              3. Inspect whether $_FILES is empty or contains an error code.
              4. Compare the file size with both upload and POST limits.
              5. Check tmp_name and is_uploaded_file().
              6. Validate size and detected file contents.
              7. Confirm the destination directory exists and is writable.
              8. Generate a safe server-side filename.
              9. Move the file and check the return value.
              10. Save a portable database value only after the move succeeds.
              11. Build the HTML URL separately from the filesystem path.
              12. Test cleanup when the database operation fails.

              Common Upload Fixes That Create Bigger Problems

              Giving the folder unrestricted permissions

              This may hide a permission issue while making the server less safe. Give only the web-server process the access it actually needs.

              Trusting the browser MIME value

              The client-provided type should not be the only content validation used by the server.

              Saving original filenames directly

              This creates collision, character, traversal and overwrite risks. Generate the storage name on the server.

              Saving the database first

              The database can contain a filename for a file that never reached permanent storage.

              Using a server path in an image URL

              PHP filesystem paths and browser URLs are not interchangeable.

              Deleting the old image too early

              If the new move or database update fails, the record may be left without either image.

              Continue Your CodeZips Project Workflow

              Technical References

              Frequently Asked Questions

              Why is $_FILES empty in PHP?

              Check that the form uses POST, includes multipart/form-data, has a named and enabled file input, and does not exceed post_max_size. Confirm that file_uploads is enabled.

              Why does move_uploaded_file() return false?

              The source may not be a valid PHP upload, the upload may already have an error, the temporary filename may be empty, or the destination directory may be missing, unwritable or incorrectly constructed.

              Why does the uploaded image show as broken?

              The HTML may be using a filesystem path instead of a browser URL, the uploads folder may not be publicly reachable, the database path may already include the folder twice, or the filename may not match the actual stored file.

              Should I store the complete upload path in MySQL?

              A filename or portable relative path is usually easier to move between localhost and hosting. Build the filesystem destination and public browser URL separately in the application.

              Is checking the file extension enough?

              No. The server should inspect the temporary file’s contents and compare the detected type with an allowlist. Image uploads can also be checked as readable images.

              Why does each upload replace the previous image?

              The code may use a fixed destination name or reuse the same original filename. Generate a unique server-side filename for each upload.

              Why does uploading work in XAMPP but fail on hosting?

              Hosting may use different size limits, permissions, case-sensitive paths, temporary storage, PHP extensions, document roots or security restrictions.

              How should I replace an existing profile image?

              Validate and move the new image first, update the database successfully, and delete the previous file only after the record safely points to the new filename.

              Does this tool upload or execute my file?

              No. It analyzes the selected settings and pasted text locally in the browser. It does not send a file to your PHP server or execute the pasted code.

              Final Takeaway

              A reliable PHP upload must prove that the form submitted multipart data, PHP accepted the request, the temporary file is genuine, the contents and size are allowed, the destination is writable, the file moved successfully, the database saved the confirmed filename and the browser uses a public URL rather than a server path.

              Leave a Comment

              Your email address will not be published. Required fields are marked *

              Scroll to Top