File Uploads and Downloads
File Uploads and Downloads Interview with follow-up questions
1. Can you explain how file uploads are handled in PHP?
In PHP, file uploads are processed through the $_FILES superglobal. When a form with enctype="multipart/form-data" is submitted with a file, PHP temporarily stores the file in the server's temp directory and populates $_FILES with metadata.
$_FILES structure for a single file input named "document":
$_FILES['document'] = [
'name' => 'report.pdf', // original filename (user-supplied — untrusted)
'type' => 'application/pdf', // MIME type (user-supplied — untrusted)
'tmp_name' => '/tmp/phpXXXXXX', // temp path on server
'error' => UPLOAD_ERR_OK, // 0 = success; see UPLOAD_ERR_* constants
'size' => 204800, // file size in bytes
];
UPLOAD_ERR_* constants:
UPLOAD_ERR_OK(0) — successUPLOAD_ERR_INI_SIZE(1) — exceedsupload_max_filesizein php.iniUPLOAD_ERR_FORM_SIZE(2) — exceedsMAX_FILE_SIZEhidden fieldUPLOAD_ERR_PARTIAL(3) — only partially uploadedUPLOAD_ERR_NO_FILE(4) — no file submitted
Secure processing pattern:
if ($_FILES['document']['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException('Upload error: ' . $_FILES['document']['error']);
}
// Validate type from file content, not from $_FILES['type']
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($_FILES['document']['tmp_name']);
if ($mime !== 'application/pdf') {
throw new RuntimeException('Only PDFs accepted');
}
// Generate a safe filename and move to permanent location
$dest = '/var/uploads/' . bin2hex(random_bytes(16)) . '.pdf';
move_uploaded_file($_FILES['document']['tmp_name'], $dest);
move_uploaded_file() verifies the file was actually uploaded via HTTP POST (not a local path attack) — always use it instead of rename() or copy().
Follow-up 1
What is the role of the $_FILES array in file uploads?
The $_FILES array in PHP is used to store information about the uploaded file. It contains several keys that provide details about the uploaded file, such as:
name: The original name of the filetype: The MIME type of the filetmp_name: The temporary location of the file on the servererror: Any error code associated with the file uploadsize: The size of the file in bytes
You can access these values using the $_FILES['key'] syntax, where 'key' is one of the keys mentioned above.
Follow-up 2
How would you validate the file type during an upload?
To validate the file type during an upload in PHP, you can use the $_FILES array to access the type key, which contains the MIME type of the uploaded file. You can then compare this value against a list of allowed file types to ensure that only specific file types are accepted. Here's an example:
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (in_array($_FILES['file']['type'], $allowedTypes)) {
// File type is valid
} else {
// File type is not allowed
}
Follow-up 3
What are some security considerations when allowing file uploads?
When allowing file uploads in PHP, there are several security considerations to keep in mind:
- File type validation: Validate the file type to ensure that only allowed file types are uploaded.
- File size limitation: Limit the size of uploaded files to prevent denial of service attacks.
- File name sanitization: Sanitize the file name to prevent directory traversal attacks.
- File storage location: Store uploaded files in a secure location outside the web root directory.
- File execution: Disable file execution for uploaded files to prevent code execution vulnerabilities.
- File permissions: Set appropriate file permissions to restrict access to uploaded files.
By implementing these security measures, you can mitigate potential risks associated with file uploads.
Follow-up 4
How can you limit the size of an uploaded file?
To limit the size of an uploaded file in PHP, you can use the upload_max_filesize and post_max_size directives in the php.ini configuration file. These directives allow you to set the maximum file size that can be uploaded. Here's an example:
upload_max_filesize = 10M
post_max_size = 10M
In this example, the maximum file size is set to 10 megabytes. Additionally, you can also check the file size in your PHP code using the $_FILES['file']['size'] value and reject the upload if it exceeds your desired limit.
2. How can you download a file using PHP?
To serve a file download in PHP, set the appropriate HTTP headers and then output the file content:
Follow-up 1
What headers need to be set for a file download?
When downloading a file using PHP, you need to set the following headers:
- Content-Description: File Transfer
- Content-Type: application/octet-stream
- Content-Disposition: attachment; filename=
- Expires: 0
- Cache-Control: must-revalidate
- Pragma: public
- Content-Length:
These headers ensure that the file is treated as a download and not displayed in the browser.
Follow-up 2
How would you handle large file downloads?
When handling large file downloads, it is important to consider memory usage and execution time. One approach is to use the readfile() function, which reads the file in chunks and outputs it directly to the browser. This avoids loading the entire file into memory. Additionally, you can use the ini_set() function to increase the maximum execution time and memory limit if needed.
Here is an example:
Follow-up 3
Can you explain how readfile() function is used in file downloads?
The readfile() function in PHP is used to read a file and output its contents directly to the browser. It takes a file path as its parameter and returns the number of bytes read or false on failure.
Here is an example of how readfile() can be used to download a file:
Follow-up 4
What are the security considerations when providing file downloads?
When providing file downloads, there are several security considerations to keep in mind:
File Validation: Ensure that the file being downloaded is valid and safe. Validate the file type, size, and content to prevent malicious files from being downloaded.
File Storage: Store the files in a secure location outside of the web root directory to prevent direct access.
User Authentication: Restrict file downloads to authenticated users only, if necessary.
File Permissions: Set appropriate file permissions to prevent unauthorized access.
Secure Connections: Use HTTPS to encrypt the file transfer and protect sensitive data.
Input Sanitization: Sanitize any user input related to file downloads to prevent directory traversal and other security vulnerabilities.
By following these security measures, you can ensure that file downloads are safe and secure for your users.
3. What is the difference between move_uploaded_file() and copy() function in PHP?
Both functions move files, but they are designed for different purposes with an important security distinction:
move_uploaded_file($tmpName, $destination)
- Specifically designed for handling files uploaded via HTTP POST.
- Verifies that the source file was actually uploaded through PHP's file upload mechanism (it must be in the temporary upload directory and tracked by PHP).
- This check prevents path traversal attacks where an attacker might supply a path to an existing server file instead of an uploaded file.
- Automatically sets appropriate permissions on the destination file.
// Safe — only moves genuine uploads
move_uploaded_file($_FILES['avatar']['tmp_name'], '/var/uploads/avatar.jpg');
copy($source, $destination)
- A general-purpose file copy function — copies any file to any location.
- No validation that the source is an uploaded file.
- Does not remove the source file (leaves the original in place).
- Can be used on any accessible file path, including potentially sensitive system files if the source is user-supplied.
// General copy — use for files already on the server
copy('/var/data/template.pdf', '/var/data/backup/template_backup.pdf');
Summary:
move_uploaded_file() |
copy() |
|
|---|---|---|
| Source validation | Upload-only (security check) | Any file |
| Source after operation | Removed (moved) | Kept (copy only) |
| Use case | Processing file uploads | General file operations |
Rule: Always use move_uploaded_file() when handling $_FILES uploads. Using copy() or rename() on $_FILES['tmp_name'] bypasses PHP's security check.
Follow-up 1
In what scenarios would you use each?
You would use the move_uploaded_file() function when you want to handle uploaded files, such as when implementing file upload functionality in a web application. This function is commonly used in scenarios where you need to move the uploaded file to a specific directory and perform additional processing on it, such as validating the file type or resizing images.
On the other hand, you would use the copy() function when you simply want to make a copy of a file and save it to a different location. This can be useful in scenarios where you need to create backups of files, duplicate files for different purposes, or transfer files between directories or servers.
Follow-up 2
What are the security implications of each?
The move_uploaded_file() function has built-in security measures to prevent unauthorized access to uploaded files. It checks that the file was indeed uploaded via HTTP POST and not through other means, and it also checks the file's permissions to ensure it is not executable. Additionally, it automatically sets the correct permissions on the file to prevent unauthorized access.
On the other hand, the copy() function does not have these built-in security measures. If you use the copy() function to copy a file, you need to manually ensure that the file is safe and that the appropriate permissions are set to prevent unauthorized access. This is especially important if the file being copied contains sensitive information or if it is accessible to the public.
Follow-up 3
How do these functions handle file permissions?
The move_uploaded_file() function automatically sets the correct permissions on the uploaded file. By default, it sets the permissions to 0644, which means the file is readable by everyone and writable only by the owner. This helps to prevent unauthorized access to the file.
On the other hand, the copy() function does not automatically set the permissions on the copied file. It inherits the permissions from the source file. If you want to set specific permissions on the copied file, you need to use the chmod() function after copying the file to change its permissions.
4. How can you handle multiple file uploads in PHP?
Handling multiple file uploads requires using array syntax in the form input name and iterating $_FILES on the server.
HTML — multiple files in one input:
Upload
PHP — $_FILES array structure for multiple uploads:
When using name="photos[]", $_FILES['photos'] contains parallel arrays:
$_FILES['photos'] = [
'name' => ['photo1.jpg', 'photo2.png'],
'type' => ['image/jpeg', 'image/png'], // untrusted
'tmp_name' => ['/tmp/phpABC', '/tmp/phpDEF'],
'error' => [0, 0],
'size' => [102400, 204800],
];
Processing:
$files = $_FILES['photos'];
$count = count($files['name']);
for ($i = 0; $i < $count; $i++) {
if ($files['error'][$i] !== UPLOAD_ERR_OK) {
continue; // skip errored uploads
}
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($files['tmp_name'][$i]);
if (!in_array($mime, ['image/jpeg', 'image/png', 'image/webp'], true)) {
continue; // skip invalid types
}
$ext = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'][$mime];
$dest = '/var/uploads/' . bin2hex(random_bytes(8)) . '.' . $ext;
move_uploaded_file($files['tmp_name'][$i], $dest);
}
upload_max_filesize and post_max_size in php.ini apply per-file and per-request respectively — set them appropriately for multiple-upload scenarios.
Follow-up 1
What changes in the $_FILES array when multiple files are uploaded?
When multiple files are uploaded, the $_FILES array is structured differently. Instead of having single values for each file attribute, such as $_FILES['file']['name'], $_FILES['file']['tmp_name'], etc., the array becomes multidimensional. Each file attribute becomes an array itself, with each element corresponding to a specific file. For example, $_FILES['file']['name'][0] would give the name of the first uploaded file, and $_FILES['file']['tmp_name'][1] would give the temporary file path of the second uploaded file.
Follow-up 2
How would you iterate over multiple uploaded files?
To iterate over multiple uploaded files, you can use a loop, such as a foreach loop, to iterate over the elements of the $_FILES array. For example, if you have a file input field with the name 'file[]', you can iterate over the uploaded files as follows:
foreach ($_FILES['file']['tmp_name'] as $key => $tmp_name) {
$file_name = $_FILES['file']['name'][$key];
$file_size = $_FILES['file']['size'][$key];
$file_type = $_FILES['file']['type'][$key];
$file_error = $_FILES['file']['error'][$key];
// Process the uploaded file
}
Follow-up 3
What are some common issues when handling multiple file uploads and how can they be mitigated?
Some common issues when handling multiple file uploads in PHP include:
File size limit: By default, PHP has a maximum file size limit that may prevent large files from being uploaded. You can increase this limit by modifying the
upload_max_filesizeandpost_max_sizedirectives in your PHP configuration.File type restrictions: PHP may restrict the types of files that can be uploaded based on the
upload_max_filesizeandpost_max_sizedirectives. You can allow additional file types by modifying theallowed_typesparameter in the$_FILESarray or by using server-side validation.File name conflicts: If multiple files with the same name are uploaded, they may overwrite each other. To mitigate this issue, you can generate unique file names by appending a timestamp or a random string to the original file name.
File upload errors: The
$_FILESarray contains an error code for each uploaded file. You can check these error codes to handle any upload errors that may occur, such as file size exceeded or file upload interrupted.
By addressing these common issues, you can ensure a smooth and reliable handling of multiple file uploads in PHP.
5. How can you track the progress of a file upload in PHP?
PHP 5.4+ supports the Upload Progress feature via the session.upload_progress.* ini directives, which track upload progress in the session without requiring a special extension.
Setup:
; php.ini
session.upload_progress.enabled = 1
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.freq = "1%" ; update frequency
session.upload_progress.min_freq = "1" ; minimum update interval in seconds
Form:
Upload
Progress polling endpoint (called by JavaScript during upload):
session_start();
$key = 'upload_progress_upload_key_123';
if (isset($_SESSION[$key])) {
$progress = $_SESSION[$key];
$percent = $progress['bytes_processed'] / $progress['content_length'] * 100;
echo json_encode(['percent' => round($percent)]);
} else {
echo json_encode(['percent' => 0]);
}
JavaScript polls this endpoint every second while the upload is in progress (using fetch or XMLHttpRequest) and updates a progress bar.
Modern alternative: For production file upload progress, direct-to-S3 uploads with a pre-signed URL are more common — the browser uploads directly to object storage, bypassing PHP entirely, and S3/the CDN provides progress events natively via the browser's XMLHttpRequest.upload.onprogress.
Follow-up 1
What PHP extensions can be used to track file upload progress?
There are several PHP extensions that can be used to track file upload progress. Some of them are:
APC(Alternative PHP Cache) - It provides a function calledapc_fetch()which can be used to retrieve the progress information stored in the cache.UploadProgress- It is a PECL extension that provides a function calleduploadprogress_get_info()which can be used to get the progress information of a file upload.
Here is an example code snippet that demonstrates how to use the UploadProgress extension to track file upload progress:
Follow-up 2
How can you provide user feedback during a file upload?
To provide user feedback during a file upload, you can use AJAX to periodically send requests to the server and retrieve the progress information. Here are the steps to do it:
- Use JavaScript to capture the file upload event and initiate an AJAX request to the server.
- In the PHP script that handles the file upload, update the progress information in the session variable as the file is being uploaded.
- Create another PHP script that can be called by the AJAX request to retrieve the progress information from the session variable.
- Use JavaScript to update the user interface with the progress information received from the server.
Here is an example code snippet that demonstrates how to provide user feedback during a file upload using AJAX:
// JavaScript code
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(event) {
if (event.lengthComputable) {
var percentComplete = (event.loaded / event.total) * 100;
// Update the user interface with the progress information
document.getElementById('progress').innerHTML = 'Upload progress: ' + percentComplete + '%';
}
});
xhr.open('POST', 'upload.php', true);
xhr.send(formData);
// PHP code in upload.php
session_start();
if (!isset($_SESSION['upload_progress'])) {
$_SESSION['upload_progress'] = [];
}
$progressKey = $_POST['progress_key'];
// Update the progress information
$_SESSION['upload_progress'][$progressKey] = $_POST['progress'];
// Remove the progress information when upload is complete
if ($_POST['progress'] == 100) {
unset($_SESSION['upload_progress'][$progressKey]);
}
Follow-up 3
What are some potential issues with tracking file upload progress and how can they be resolved?
There are a few potential issues that can arise when tracking file upload progress in PHP. Here are some of them and their possible resolutions:
Session locking: When multiple requests are made to update the session variable simultaneously, session locking can occur, causing delays or conflicts. To resolve this, you can use
session_write_close()function to release the session lock after updating the progress information.Large file uploads: If a large file is being uploaded, it may take a long time to complete the upload, causing the PHP script to exceed the maximum execution time limit. To resolve this, you can increase the
max_execution_timeconfiguration in PHP.ini or use theset_time_limit()function to set a longer execution time limit for the script.Browser compatibility: Some older browsers may not support the necessary JavaScript and AJAX features required for tracking file upload progress. To ensure compatibility, you can use feature detection and fallback mechanisms to provide a consistent user experience.
Security: Storing progress information in the session variable may pose security risks if not handled properly. To enhance security, you can encrypt the progress information before storing it in the session variable and decrypt it when retrieving it.
These are just a few examples of potential issues and their resolutions. The specific issues and resolutions may vary depending on the implementation and requirements of your application.
Live mock interview
Mock interview: File Uploads and Downloads
- Read your scene and goals
- Talk it out; goals tick off live
- Get a score and stronger lines
Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.