Session 4.7 – PHP File Handling

Module 4: Server-Side Scripting – PHP | Duration: 1 hr

Learning Objectives

By the end of this session, students will be able to:

  • Read files using various PHP functions
  • Write and append data to files
  • Perform file operations (copy, rename, delete)
  • Work with directories and directory contents
  • Handle file uploads securely
  • Implement proper file permissions and security measures

Introduction to File Handling

PHP provides extensive capabilities for working with the filesystem. File handling is essential for storing data, managing uploads, generating reports, and many other web application features.

Common Use Cases
  • Data Storage: Save application data in text or JSON files
  • Logging: Write application logs and error messages
  • File Uploads: Handle user-uploaded images and documents
  • Configuration: Read and write configuration files
  • Export/Import: Generate CSV, PDF reports
  • Caching: Store cached data in files

Reading Files

file_get_contents() - Read Entire File
    
<?php
// Read entire file into string
$content = file_get_contents('data.txt');
echo $content;

// Check if file exists first
if (file_exists('data.txt')) {
    $content = file_get_contents('data.txt');
} else {
    echo "File not found";
}

// Read from URL
$html = file_get_contents('https://example.com');

// With error handling
$content = @file_get_contents('data.txt');
if ($content === false) {
    echo "Error reading file";
}
?>
file() - Read File into Array
    
<?php
// Read file into array (one line per element)
$lines = file('data.txt');

foreach ($lines as $line) {
    echo htmlspecialchars($line) . "<br>";
}

// Remove newlines
$lines = file('data.txt', FILE_IGNORE_NEW_LINES);

// Skip empty lines
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
?>
fopen(), fread(), fclose() - File Pointers
    
<?php
// Open file for reading
$handle = fopen('data.txt', 'r');

if ($handle) {
    // Read entire file
    $content = fread($handle, filesize('data.txt'));
    echo $content;

    // Close file
    fclose($handle);
}

// Read line by line
$handle = fopen('data.txt', 'r');
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        echo htmlspecialchars($line) . "<br>";
    }
    fclose($handle);
}

// Read character by character
$handle = fopen('data.txt', 'r');
if ($handle) {
    while (($char = fgetc($handle)) !== false) {
        echo $char;
    }
    fclose($handle);
}
?>
Reading CSV Files
    
<?php
// Read CSV file
$handle = fopen('data.csv', 'r');

if ($handle) {
    // Read header row
    $header = fgetcsv($handle);

    // Read data rows
    while (($data = fgetcsv($handle)) !== false) {
        echo "Name: {$data[0]}, Email: {$data[1]}<br>";
    }

    fclose($handle);
}

// Alternative: read CSV into array
$rows = array_map('str_getcsv', file('data.csv'));
$header = array_shift($rows);

foreach ($rows as $row) {
    $record = array_combine($header, $row);
    echo "Name: {$record['name']}, Email: {$record['email']}<br>";
}
?>

Writing Files

file_put_contents() - Write Entire File
    
<?php
// Write string to file (overwrites)
$data = "Hello, World!";
file_put_contents('output.txt', $data);

// Append to file
file_put_contents('log.txt', $data, FILE_APPEND);

// Append with newline
file_put_contents('log.txt', $data . PHP_EOL, FILE_APPEND);

// Write array to file
$lines = array("Line 1", "Line 2", "Line 3");
file_put_contents('output.txt', implode(PHP_EOL, $lines));

// Check success
$bytes = file_put_contents('output.txt', $data);
if ($bytes === false) {
    echo "Error writing file";
} else {
    echo "$bytes bytes written";
}
?>
fopen(), fwrite(), fclose() - File Pointers
    
<?php
// Open file for writing (overwrites)
$handle = fopen('output.txt', 'w');
if ($handle) {
    fwrite($handle, "Hello, World!\n");
    fwrite($handle, "Second line\n");
    fclose($handle);
}

// Append mode
$handle = fopen('log.txt', 'a');
if ($handle) {
    fwrite($handle, date('Y-m-d H:i:s') . " - Log message\n");
    fclose($handle);
}

// File modes
// 'r'  - Read only
// 'r+' - Read and write
// 'w'  - Write only (create/truncate)
// 'w+' - Read and write (create/truncate)
// 'a'  - Append (create if not exists)
// 'a+' - Read and append
// 'x'  - Create new file (fails if exists)
?>
Writing CSV Files
    
<?php
// Write array to CSV
$data = array(
    array('Name', 'Email', 'Age'),
    array('John Doe', 'john@example.com', 30),
    array('Jane Smith', 'jane@example.com', 25)
);

$handle = fopen('output.csv', 'w');
if ($handle) {
    foreach ($data as $row) {
        fputcsv($handle, $row);
    }
    fclose($handle);
}

// Write with custom delimiter
$handle = fopen('output.csv', 'w');
if ($handle) {
    foreach ($data as $row) {
        fputcsv($handle, $row, ';');  // Semicolon delimiter
    }
    fclose($handle);
}
?>
Writing JSON Files
    
<?php
// Write data as JSON
$data = array(
    'users' => array(
        array('name' => 'John', 'email' => 'john@example.com'),
        array('name' => 'Jane', 'email' => 'jane@example.com')
    )
);

// Write formatted JSON
$json = json_encode($data, JSON_PRETTY_PRINT);
file_put_contents('data.json', $json);

// Read JSON
$json = file_get_contents('data.json');
$data = json_decode($json, true);  // true for associative array

foreach ($data['users'] as $user) {
    echo $user['name'] . ": " . $user['email'] . "<br>";
}
?>

File Operations

File Information
    
<?php
$file = 'data.txt';

// Check if file exists
if (file_exists($file)) {
    echo "File exists\n";
}

// Check if it's a file (not directory)
if (is_file($file)) {
    echo "It's a file\n";
}

// Check if readable/writable
if (is_readable($file)) {
    echo "Readable\n";
}
if (is_writable($file)) {
    echo "Writable\n";
}

// Get file size
$size = filesize($file);
echo "Size: $size bytes\n";

// Get last modified time
$mtime = filemtime($file);
echo "Modified: " . date('Y-m-d H:i:s', $mtime) . "\n";

// Get file information
$info = pathinfo($file);
echo "Directory: " . $info['dirname'] . "\n";
echo "Filename: " . $info['basename'] . "\n";
echo "Extension: " . $info['extension'] . "\n";
echo "Name: " . $info['filename'] . "\n";

// Get MIME type
$mime = mime_content_type($file);
echo "MIME type: $mime\n";
?>
Copy, Rename, Delete
    
<?php
// Copy file
if (copy('source.txt', 'destination.txt')) {
    echo "File copied successfully";
}

// Rename/Move file
if (rename('old.txt', 'new.txt')) {
    echo "File renamed successfully";
}

// Move to different directory
rename('file.txt', 'archive/file.txt');

// Delete file
if (unlink('unwanted.txt')) {
    echo "File deleted successfully";
}

// Delete with error checking
if (file_exists('temp.txt')) {
    if (unlink('temp.txt')) {
        echo "Deleted successfully";
    } else {
        echo "Error deleting file";
    }
}
?>
File Permissions
    
<?php
// Change file permissions
chmod('data.txt', 0644);  // Owner: rw, Group: r, Others: r
chmod('script.php', 0755); // Owner: rwx, Group: rx, Others: rx

// Get file permissions
$perms = fileperms('data.txt');
echo substr(sprintf('%o', $perms), -4);  // Last 4 digits

// Check specific permissions
if (is_readable('data.txt') && is_writable('data.txt')) {
    echo "Can read and write";
}

// Change file owner (requires privileges)
chown('data.txt', 'www-data');
chgrp('data.txt', 'www-data');
?>

Directory Operations

Create and Delete Directories
    
<?php
// Create directory
if (mkdir('uploads', 0755)) {
    echo "Directory created";
}

// Create nested directories
mkdir('path/to/directory', 0755, true);

// Delete empty directory
if (rmdir('temp')) {
    echo "Directory removed";
}

// Delete directory with contents
function deleteDirectory($dir) {
    if (!file_exists($dir)) {
        return true;
    }

    if (!is_dir($dir)) {
        return unlink($dir);
    }

    foreach (scandir($dir) as $item) {
        if ($item == '.' || $item == '..') {
            continue;
        }

        if (!deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }
    }

    return rmdir($dir);
}

// Usage
deleteDirectory('temp_folder');
?>
List Directory Contents
    
<?php
// Using scandir()
$files = scandir('uploads');
foreach ($files as $file) {
    if ($file != '.' && $file != '..') {
        echo $file . "<br>";
    }
}

// Using glob() - with pattern matching
$files = glob('uploads/*.jpg');
foreach ($files as $file) {
    echo basename($file) . "<br>";
}

// All PHP files
$files = glob('*.php');

// All files and directories
$items = glob('*');

// Using DirectoryIterator
$dir = new DirectoryIterator('uploads');
foreach ($dir as $file) {
    if (!$file->isDot()) {
        echo $file->getFilename();
        echo " - " . $file->getSize() . " bytes";
        echo " - " . ($file->isDir() ? "Directory" : "File");
        echo "<br>";
    }
}

// Recursive directory listing
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('uploads'),
    RecursiveIteratorIterator::SELF_FIRST
);

foreach ($iterator as $file) {
    if (!$file->isDot()) {
        echo str_repeat('-', $iterator->getDepth()) . ' ';
        echo $file->getFilename() . "<br>";
    }
}
?>

Handling File Uploads

Upload Form
    
<!-- upload.html -->
<form action="upload.php" method="post" enctype="multipart/form-data">
    <label>Select file:</label>
    <input type="file" name="fileToUpload" required>
    <button type="submit">Upload</button>
</form>

<!-- Multiple files -->
<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="files[]" multiple>
    <button type="submit">Upload Files</button>
</form>
Secure File Upload Handler
    
<?php
// upload.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // Check if file was uploaded
    if (!isset($_FILES['fileToUpload']) || $_FILES['fileToUpload']['error'] !== UPLOAD_ERR_OK) {
        die('Upload failed');
    }

    $file = $_FILES['fileToUpload'];

    // File properties
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileError = $file['error'];
    $fileType = $file['type'];

    // Validate file extension
    $allowedExtensions = array('jpg', 'jpeg', 'png', 'gif', 'pdf');
    $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));

    if (!in_array($fileExtension, $allowedExtensions)) {
        die('Invalid file type. Allowed: ' . implode(', ', $allowedExtensions));
    }

    // Validate file size (5MB max)
    $maxSize = 5 * 1024 * 1024;
    if ($fileSize > $maxSize) {
        die('File too large. Maximum size: 5MB');
    }

    // Validate MIME type
    $allowedMimeTypes = array('image/jpeg', 'image/png', 'image/gif', 'application/pdf');
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $fileTmpName);
    finfo_close($finfo);

    if (!in_array($mimeType, $allowedMimeTypes)) {
        die('Invalid file type');
    }

    // Generate unique filename
    $newFileName = uniqid('', true) . '.' . $fileExtension;

    // Upload directory
    $uploadDir = 'uploads/';

    // Create directory if not exists
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }

    // Full path
    $destination = $uploadDir . $newFileName;

    // Move uploaded file
    if (move_uploaded_file($fileTmpName, $destination)) {
        echo "File uploaded successfully: $newFileName";

        // Additional processing (resize image, scan for viruses, etc.)
    } else {
        echo "Error uploading file";
    }
}
?>
Multiple File Upload
    
<?php
// Handle multiple files
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['files'])) {

    $files = $_FILES['files'];
    $uploadDir = 'uploads/';
    $uploadedFiles = array();
    $errors = array();

    // Create upload directory
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }

    // Process each file
    for ($i = 0; $i < count($files['name']); $i++) {

        $fileName = $files['name'][$i];
        $fileTmpName = $files['tmp_name'][$i];
        $fileSize = $files['size'][$i];
        $fileError = $files['error'][$i];

        // Check for errors
        if ($fileError !== UPLOAD_ERR_OK) {
            $errors[] = "$fileName: Upload error";
            continue;
        }

        // Validate extension
        $allowedExtensions = array('jpg', 'jpeg', 'png', 'gif');
        $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));

        if (!in_array($fileExtension, $allowedExtensions)) {
            $errors[] = "$fileName: Invalid file type";
            continue;
        }

        // Validate size (2MB max)
        if ($fileSize > 2 * 1024 * 1024) {
            $errors[] = "$fileName: File too large";
            continue;
        }

        // Generate unique name
        $newFileName = uniqid('', true) . '.' . $fileExtension;
        $destination = $uploadDir . $newFileName;

        // Move file
        if (move_uploaded_file($fileTmpName, $destination)) {
            $uploadedFiles[] = $newFileName;
        } else {
            $errors[] = "$fileName: Failed to move file";
        }
    }

    // Display results
    if (!empty($uploadedFiles)) {
        echo "<h3>Uploaded Files:</h3>";
        foreach ($uploadedFiles as $file) {
            echo "<div>$file</div>";
        }
    }

    if (!empty($errors)) {
        echo "<h3>Errors:</h3>";
        foreach ($errors as $error) {
            echo "<div class='alert alert-danger'>$error</div>";
        }
    }
}
?>
Upload Security Best Practices
  • Validate file extensions: Use whitelist approach
  • Verify MIME type: Check actual file content, not just extension
  • Limit file size: Prevent disk space exhaustion
  • Rename files: Use unique names to prevent overwrites
  • Store outside web root: Prevent direct access to uploaded files
  • Scan for malware: Use antivirus tools
  • Set proper permissions: Prevent execution of uploaded files
  • Implement rate limiting: Prevent abuse

Session Summary

Key Points
  • PHP provides multiple functions for reading files: file_get_contents(), file(), fopen()/fread()
  • Writing files can be done with file_put_contents() or fopen()/fwrite()
  • File operations include copy(), rename(), unlink(), and file information functions
  • Directory operations: mkdir(), rmdir(), scandir(), glob(), DirectoryIterator
  • File uploads require proper validation and security measures
  • Always validate file extensions, MIME types, and sizes
  • Use unique filenames and proper permissions for uploaded files
  • Handle errors gracefully and provide user feedback
Next Session Preview

In the next session, we will explore PHP-MySQL Connectivity, learning how to connect PHP applications to MySQL databases and execute queries securely.