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.
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
Mobile applications frequently need to upload files such as:
A REST API provides a standard way for the mobile application to send these files to the backend.
User Selects File
↓
React Native
↓
FormData
↓
POST Request
↓
PHP API
↓
Validation
↓
Upload Directory
↓
Database File Path
↓
JSON Response
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.
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.
PHP provides uploaded file information through the
$_FILES superglobal.
$_FILES['file']
It can contain information such as:
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.
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.
$tmpName =
$_FILES['file']['tmp_name'];
PHP temporarily stores the uploaded file before it is moved to the application's upload directory.
$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.
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.
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.
$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.
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.
$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.
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.
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.
$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.
<?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
]);
?>
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.
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
);
$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.
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.
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.
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.
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.
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
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.
$_FILES.move_uploaded_file() to move uploaded files.Question: Which PHP superglobal contains information about uploaded files?