Lesson 86 of 158 – File Upload API
86%

File Upload API

A File Upload API allows a client application such as React Native to send files to a server. The PHP REST API receives the uploaded file, validates it, stores it safely, and returns a JSON response.

Note: File uploads require additional security checks. Never trust the original filename, extension, MIME type, or file size sent by the client.

1. What is a File Upload API?

A File Upload API is an endpoint that accepts a file from a client application and stores or processes it on the server.

React Native App
       ↓
File Upload Request
       ↓
PHP REST API
       ↓
Validate File
       ↓
Save File
       ↓
JSON Response

2. Why File Upload APIs are Needed

Mobile applications frequently need to upload files such as:

  • Profile photos
  • Student documents
  • Assignment files
  • PDF documents
  • Images
  • Certificates

A REST API provides a standard way for the mobile application to send these files to the backend.

3. File Upload Flow

User Selects File
       ↓
React Native
       ↓
FormData
       ↓
POST Request
       ↓
PHP API
       ↓
Validation
       ↓
Upload Directory
       ↓
Database File Path
       ↓
JSON Response

4. HTTP Method for File Upload

The POST method is commonly used for file uploads.

POST
/api/upload.php

The request normally uses multipart/form-data rather than a normal JSON request body.

5. multipart/form-data

Files are commonly sent using the multipart/form-data request format.

Content-Type:
multipart/form-data

This format can contain both files and normal form fields.

6. PHP $_FILES

PHP provides uploaded file information through the $_FILES superglobal.

$_FILES['file']

It can contain information such as:

  • Original filename
  • Temporary file location
  • File size
  • Upload error code
  • Uploaded file type

7. Checking Whether a File Was Uploaded

if (
    !isset($_FILES['file'])
) {

    http_response_code(400);

    echo json_encode([
        "success" => false,
        "message" =>
            "File is required"
    ]);

    exit;
}

Always check that the expected upload field exists before processing it.

8. Checking Upload Errors

if (
    $_FILES['file']['error']
    !== UPLOAD_ERR_OK
) {

    http_response_code(400);

    echo json_encode([
        "success" => false,
        "message" =>
            "File upload failed"
    ]);

    exit;
}

PHP provides predefined constants such as UPLOAD_ERR_OK for checking upload status.

9. Getting the Temporary File Path

$tmpName =
    $_FILES['file']['tmp_name'];

PHP temporarily stores the uploaded file before it is moved to the application's upload directory.

10. Getting the Original Filename

$originalName =
    $_FILES['file']['name'];

The original filename should not be trusted or directly used as the server filename.

For example, instead of storing:

student-photo.jpg

the application can generate a unique server-side filename.

11. Checking File Size

Large files can consume server storage and resources. Always define a maximum file size.

$maxSize =
    5 * 1024 * 1024;

if (
    $_FILES['file']['size']
    > $maxSize
) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "File is too large"
    ]);

    exit;
}

The example allows files up to 5 MB.

12. File Extension

The extension can be extracted using PHP:

$extension =
    strtolower(
        pathinfo(
            $_FILES['file']['name'],
            PATHINFO_EXTENSION
        )
    );

Do not rely only on the extension for security. It should be combined with MIME/type validation and other checks.

13. Allow Specific Extensions

$allowedExtensions = [
    'jpg',
    'jpeg',
    'png',
    'pdf'
];

if (
    !in_array(
        $extension,
        $allowedExtensions,
        true
    )
) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "File type not allowed"
    ]);

    exit;
}

Only extensions required by your application should be allowed.

14. MIME Type Validation

MIME type information can be checked using PHP's finfo functionality.

$finfo = new finfo(
    FILEINFO_MIME_TYPE
);

$mimeType =
    $finfo->file(
        $_FILES['file']['tmp_name']
    );

This provides information about the detected file type.

15. Allow Specific MIME Types

$allowedMimeTypes = [
    'image/jpeg',
    'image/png',
    'application/pdf'
];

if (
    !in_array(
        $mimeType,
        $allowedMimeTypes,
        true
    )
) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "Invalid file type"
    ]);

    exit;
}

For security-sensitive uploads, validate the actual file type rather than trusting a client-provided Content-Type header.

16. Generate a Unique Filename

Do not depend on the original filename for storage.

$newName =
    bin2hex(
        random_bytes(16)
    )
    . '.'
    . $extension;

A server-generated filename reduces filename collisions and avoids trusting user-controlled names.

17. Upload Directory

Create a dedicated directory for uploaded files.

$uploadDir =
    __DIR__ . '/uploads/';

if (!is_dir($uploadDir)) {

    mkdir(
        $uploadDir,
        0755,
        true
    );
}

The directory permissions and web-server configuration should be reviewed carefully in production.

18. Moving the Uploaded File

$destination =
    $uploadDir . $newName;

if (
    !move_uploaded_file(
        $_FILES['file']['tmp_name'],
        $destination
    )
) {

    http_response_code(500);

    echo json_encode([
        "success" => false,
        "message" =>
            "Unable to save file"
    ]);

    exit;
}

move_uploaded_file() is designed for moving an uploaded file to its final location.

19. Complete Basic Upload API

<?php

header(
    "Content-Type: application/json"
);

if (
    !isset($_FILES['file'])
) {

    http_response_code(400);

    echo json_encode([
        "success" => false,
        "message" =>
            "File is required"
    ]);

    exit;
}

$file = $_FILES['file'];

if (
    $file['error']
    !== UPLOAD_ERR_OK
) {

    http_response_code(400);

    echo json_encode([
        "success" => false,
        "message" =>
            "Upload failed"
    ]);

    exit;
}

$maxSize =
    5 * 1024 * 1024;

if ($file['size'] > $maxSize) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "File is too large"
    ]);

    exit;
}

$extension =
    strtolower(
        pathinfo(
            $file['name'],
            PATHINFO_EXTENSION
        )
    );

$allowedExtensions = [
    'jpg',
    'jpeg',
    'png',
    'pdf'
];

if (
    !in_array(
        $extension,
        $allowedExtensions,
        true
    )
) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "File type not allowed"
    ]);

    exit;
}

$newName =
    bin2hex(
        random_bytes(16)
    )
    . '.'
    . $extension;

$uploadDir =
    __DIR__ . '/uploads/';

if (!is_dir($uploadDir)) {

    mkdir(
        $uploadDir,
        0755,
        true
    );
}

$destination =
    $uploadDir . $newName;

if (
    !move_uploaded_file(
        $file['tmp_name'],
        $destination
    )
) {

    http_response_code(500);

    echo json_encode([
        "success" => false,
        "message" =>
            "Unable to save file"
    ]);

    exit;
}

echo json_encode([
    "success" => true,
    "message" =>
        "File uploaded successfully",
    "filename" =>
        $newName
]);

?>

20. Upload File with Additional Data

A multipart request can contain both a file and normal form fields.

$studentId =
    $_POST['student_id']
    ?? '';

$title =
    $_POST['title']
    ?? '';

$file =
    $_FILES['file']
    ?? null;

For example, a student can upload an assignment together with the student ID and assignment title.

21. Store File Information in MySQL

The actual file can be stored on the server while information about the file is stored in the database.

CREATE TABLE uploads (
    id INT AUTO_INCREMENT PRIMARY KEY,
    student_id INT NOT NULL,
    filename VARCHAR(255) NOT NULL,
    original_name VARCHAR(255) NOT NULL,
    mime_type VARCHAR(100) NOT NULL,
    file_size INT NOT NULL,
    created_at TIMESTAMP
        DEFAULT CURRENT_TIMESTAMP
);

22. Insert File Information Safely

$stmt = $pdo->prepare(
    "INSERT INTO uploads
    (
        student_id,
        filename,
        original_name,
        mime_type,
        file_size
    )
    VALUES (?, ?, ?, ?, ?)"
);

$stmt->execute([
    $studentId,
    $newName,
    $file['name'],
    $mimeType,
    $file['size']
]);

Use prepared statements when saving upload information to MySQL.

23. React Native FormData

React Native can send a selected file using FormData.

const formData =
    new FormData();

formData.append(
    "file",
    {
        uri: file.uri,
        name: file.name,
        type: file.type
    }
);

The exact file-picker object depends on the library used by the React Native application.

24. React Native Upload with Fetch

const response =
    await fetch(
        "https://example.com/api/upload.php",
        {
            method: "POST",
            body: formData
        }
    );

const result =
    await response.json();

console.log(result);

When using FormData, allow the networking implementation to construct the multipart request boundary correctly.

25. Upload with Authentication

A private file upload API should normally authenticate the request. For example, a JWT can be sent using the Authorization header.

Authorization:
Bearer YOUR_JWT_TOKEN

The API should verify the token before associating the uploaded file with the authenticated user.

26. File Upload Security

  • Limit file size.
  • Allow only required file types.
  • Validate the actual file type.
  • Generate server-side filenames.
  • Never trust the original filename.
  • Never trust the client-provided MIME type alone.
  • Use authentication for private uploads.
  • Use authorization to control who can upload.
  • Store files in an appropriately configured directory.
  • Do not expose unnecessary server information.

27. Common File Upload Mistakes

  • Allowing every file extension.
  • Accepting unlimited file sizes.
  • Using the original filename directly.
  • Trusting the client MIME type.
  • Skipping upload error checks.
  • Saving files without unique names.
  • Not checking authorization.
  • Storing sensitive files without access control.
  • Building database queries with raw upload information.

28. Testing File Upload with Postman

Postman can test a multipart file upload.

Select:

POST
Body
 ↓
form-data
 ↓
Key: file
Type: File
 ↓
Select File

You can also add fields such as student_id or title.

29. Complete Mobile File Upload Flow

React Native
      ↓
Select File
      ↓
Create FormData
      ↓
POST Multipart Request
      ↓
JWT Authentication
      ↓
PHP REST API
      ↓
Validate File
      ↓
Generate Filename
      ↓
Save File
      ↓
Save Metadata
      ↓
JSON Response
      ↓
React Native

30. File Upload API Summary

A secure file upload API receives multipart form data, validates the file, generates a safe server-side filename, stores the file, optionally stores its metadata in MySQL, and returns a JSON response.

File
 ↓
Validate
 ↓
Generate Safe Name
 ↓
Move File
 ↓
Store Metadata
 ↓
Return JSON

This approach can be used for profile photos, student documents, assignments, certificates, and other files in a React Native application.

📌 Key Points

  • File uploads commonly use POST and multipart/form-data.
  • PHP provides uploaded file information through $_FILES.
  • Always check the upload error status.
  • Always validate file size.
  • Allow only the file types required by the application.
  • Do not trust the original filename.
  • Generate unique server-side filenames.
  • Validate the actual file type where appropriate.
  • Use move_uploaded_file() to move uploaded files.
  • Use prepared statements when storing file metadata in MySQL.
  • Private upload APIs should use authentication and authorization.
  • React Native can use FormData to upload files.
  • Postman can test multipart/form-data uploads.
  • Never allow unrestricted file uploads in a production API.
  • The next lesson will cover image upload APIs.

🧠 Quick Quiz

Question: Which PHP superglobal contains information about uploaded files?