PHP – Use Case 3: Creating a File Upload and Management System

Project Overview

A File Upload and Management System allows users to upload, view, download, and delete files. This project involves handling file uploads securely, storing file information in a database, and managing user interactions with the files using PHP and MySQL.

Prerequisites

Ensure you have the following:

  • Web Server: Apache (using XAMPP, WAMP, or MAMP)
  • PHP: Version 7.4 or higher
  • MySQL: For database management
  • Code Editor: VS Code, Sublime Text, PHPStorm, etc.
  • Composer: For dependency management (optional)

Step-by-Step Procedure

1. Setting Up the Development Environment

  1. Install XAMPP:
    • Download from XAMPP Official Website.
    • Follow the installation wizard and install it in the default directory.
  2. Start Apache and MySQL:
    • Open the XAMPP Control Panel.
    • Start the Apache and MySQL modules.

2. Creating the Database

  1. Access phpMyAdmin:
    • Navigate to http://localhost/phpmyadmin/ in your browser.
  2. Create a New Database:
    • Click on “New” in the left sidebar.
    • Name the database file_manager.
    • Choose “utf8mb4_unicode_ci” as the collation.
    • Click “Create”.
  3. Create a files Table:
    • Select the file_manager database.
    • Click on “New” to create a table.
    • Define the table with the following fields:
    Field Type Null Key Default Extra id INT NO PRI NULL AUTO_INCREMENT filename VARCHAR(255) NO NULL filepath VARCHAR(255) NO NULL uploaded_by VARCHAR(100) NO NULL uploaded_at TIMESTAMP NO CURRENT_TIMESTAMP
    • Click “Save”.

3. Project Structure

Organize your project files as follows:

file-manager/
├── uploads/           # Directory to store uploaded files
├── assets/
│   ├── css/
│   │   └── styles.css
│   └── js/
│       └── scripts.js
├── config/
│   └── db.php
├── templates/
│   ├── header.php
│   └── footer.php
├── upload.php
├── view_files.php
├── download.php
├── delete_file.php
└── README.md

Note: Ensure that the uploads/ directory is writable by the web server.

4. Configuration

a. Database Connection (config/db.php)
<?php
// config/db.php

$host = 'localhost';
$db   = 'file_manager';
$user = 'root'; // Default XAMPP MySQL user
$pass = '';     // Default XAMPP MySQL password is empty
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION, // Enable exceptions
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,       // Fetch associative arrays
    PDO::ATTR_EMULATE_PREPARES   => false,                  // Disable emulation
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    // Handle connection errors
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>

5. Creating Reusable Templates

a. Header (templates/header.php)
<?php
// templates/header.php
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File Upload and Management System</title>
    <link rel="stylesheet" href="/file-manager/assets/css/styles.css">
</head>
<body>
    <header>
        <h1>File Upload and Management System</h1>
        <nav>
            <a href="/file-manager/upload.php">Upload File</a>
            <a href="/file-manager/view_files.php">View Files</a>
        </nav>
    </header>
    <main>
b. Footer (templates/footer.php)
<?php
// templates/footer.php
?>
    </main>
    <footer>
        <p>&copy; <?php echo date("Y"); ?> Your Company Name</p>
    </footer>
    <script src="/file-manager/assets/js/scripts.js"></script>
</body>
</html>

6. Styling the Application (assets/css/styles.css)

Add basic styles to enhance the appearance.

/* assets/css/styles.css */

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

header, footer {
    background-color: #555;
    color: #fff;
    padding: 10px 20px;
}

header h1, footer p {
    margin: 0;
}

nav a {
    color: #fff;
    margin-right: 15px;
    text-decoration: none;
}

main {
    padding: 20px;
}

form {
    max-width: 500px;
    margin: auto;
}

.form-group {
    margin-bottom: 15px;
}

label {
    display: block;
    margin-bottom: 5px;
}

input[type="file"],
input[type="text"] {
    width: 100%;
    padding: 8px;
    box-sizing: border-box;
}

button {
    padding: 10px 15px;
    background-color: #28a745;
    color: #fff;
    border: none;
    cursor: pointer;
}

button:hover {
    background-color: #218838;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
}

table, th, td {
    border: 1px solid #ddd;
}

th, td {
    padding: 12px;
    text-align: left;
}

th {
    background-color: #f4f4f4;
}

a {
    color: #007BFF;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

.error {
    background-color: #f2dede;
    color: #a94442;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid #ebccd1;
    border-radius: 4px;
}

.success {
    background-color: #dff0d8;
    color: #3c763d;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid #d6e9c6;
    border-radius: 4px;
}

7. Implementing File Upload (upload.php)

This page allows users to upload files to the server.

<?php
// upload.php

require 'config/db.php';
require 'templates/header.php';

$errors = [];
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Check if file was uploaded without errors
    if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
        $fileTmpPath = $_FILES['file']['tmp_name'];
        $originalName = $_FILES['file']['name'];
        $fileSize = $_FILES['file']['size'];
        $fileType = $_FILES['file']['type'];
        $fileNameCmps = explode(".", $originalName);
        $fileExtension = strtolower(end($fileNameCmps));

        // Sanitize file name
        $newFileName = md5(time() . $originalName) . '.' . $fileExtension;

        // Allowed file extensions
        $allowedfileExtensions = ['jpg', 'gif', 'png', 'txt', 'xls', 'doc', 'pdf'];

        if (in_array($fileExtension, $allowedfileExtensions)) {
            // Directory in which the uploaded file will be moved
            $uploadFileDir = './uploads/';
            $dest_path = $uploadFileDir . $newFileName;

            if(move_uploaded_file($fileTmpPath, $dest_path)) 
            {
                // Insert file info into database
                $uploaded_by = 'Admin'; // Replace with dynamic user info if applicable
                $stmt = $pdo->prepare('INSERT INTO files (filename, filepath, uploaded_by) VALUES (?, ?, ?)');
                if ($stmt->execute([$originalName, $newFileName, $uploaded_by])) {
                    $success = 'File is successfully uploaded.';
                } else {
                    $errors[] = 'There was an error saving the file information to the database.';
                }
            }
            else 
            {
                $errors[] = 'There was an error moving the uploaded file.';
            }
        }
        else
        {
            $errors[] = 'Upload failed. Allowed file types: ' . implode(',', $allowedfileExtensions);
        }
    }
    else
    {
        $errors[] = 'There is some error in the file upload. Please check the following error.<br>';
        $errors[] = 'Error:' . $_FILES['file']['error'];
    }
}
?>

<h2>Upload File</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo htmlspecialchars($success); ?></p>
    </div>
<?php endif; ?>

<form action="upload.php" method="POST" enctype="multipart/form-data">
    <div class="form-group">
        <label for="file">Choose File:</label>
        <input type="file" id="file" name="file" required>
    </div>
    <button type="submit">Upload</button>
</form>

<?php
require 'templates/footer.php';
?>

8. Viewing Uploaded Files (view_files.php)

This page lists all uploaded files with options to download or delete them.

<?php
// view_files.php

require 'config/db.php';
require 'templates/header.php';

// Fetch all files
$stmt = $pdo->query('SELECT * FROM files ORDER BY uploaded_at DESC');
$files = $stmt->fetchAll();
?>

<h2>Uploaded Files</h2>

<?php if ($files): ?>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>Filename</th>
                <th>Uploaded By</th>
                <th>Uploaded At</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($files as $file): ?>
                <tr>
                    <td><?php echo htmlspecialchars($file['id']); ?></td>
                    <td><?php echo htmlspecialchars($file['filename']); ?></td>
                    <td><?php echo htmlspecialchars($file['uploaded_by']); ?></td>
                    <td><?php echo htmlspecialchars($file['uploaded_at']); ?></td>
                    <td>
                        <a href="download.php?id=<?php echo $file['id']; ?>">Download</a> |
                        <a href="delete_file.php?id=<?php echo $file['id']; ?>" onclick="return confirm('Are you sure you want to delete this file?');">Delete</a>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
<?php else: ?>
    <p>No files uploaded yet.</p>
<?php endif; ?>

<?php
require 'templates/footer.php';
?>

9. Downloading Files (download.php)

This script handles the downloading of files.

<?php
// download.php

require 'config/db.php';

// Get file ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch file details
$stmt = $pdo->prepare('SELECT * FROM files WHERE id = ?');
$stmt->execute([$id]);
$file = $stmt->fetch();

if ($file) {
    $filePath = './uploads/' . $file['filepath'];
    if (file_exists($filePath)) {
        // Set headers
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.basename($file['filename']).'"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($filePath));
        // Clear output buffer
        ob_clean();
        flush();
        // Read the file
        readfile($filePath);
        exit;
    } else {
        echo "<p>File not found.</p>";
    }
} else {
    echo "<p>Invalid file ID.</p>";
}
?>

10. Deleting Files (delete_file.php)

This script handles the deletion of files from both the server and the database.

<?php
// delete_file.php

require 'config/db.php';

// Get file ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch file details
$stmt = $pdo->prepare('SELECT * FROM files WHERE id = ?');
$stmt->execute([$id]);
$file = $stmt->fetch();

if ($file) {
    $filePath = './uploads/' . $file['filepath'];
    // Delete file from server
    if (file_exists($filePath)) {
        unlink($filePath);
    }
    // Delete from database
    $stmt = $pdo->prepare('DELETE FROM files WHERE id = ?');
    $stmt->execute([$id]);
    // Redirect to view files page
    header('Location: view_files.php');
    exit;
} else {
    echo "<p>Invalid file ID.</p>";
}
?>

11. Testing the Application

  1. Access the Upload Page:
    • Navigate to http://localhost/file-manager/upload.php.
    • Upload a file and submit.
    • Verify that the file appears in the uploads/ directory and is listed on the “View Files” page.
  2. View Uploaded Files:
    • Navigate to http://localhost/file-manager/view_files.php.
    • Ensure all uploaded files are listed with options to download or delete.
  3. Download a File:
    • Click on “Download” next to a file.
    • Verify that the file is downloaded correctly.
  4. Delete a File:
    • Click on “Delete” next to a file.
    • Confirm the deletion.
    • Ensure the file is removed from both the server and the database.

12. Deployment Considerations

When deploying to a live server:

  • Secure the uploads/ Directory:
    • Prevent direct access to uploaded files by using .htaccess to restrict access or store files outside the web root.
    Example .htaccess to Deny Access: # Deny access to all files Deny from all
  • Validate File Types and Sizes:
    • Strictly enforce allowed file types and size limits to prevent malicious uploads.
  • Use HTTPS:
    • Ensure your website uses HTTPS for encrypted data transmission.
  • Regular Backups:
    • Implement regular backups of your database and uploaded files.
  • Error Reporting:
    • Disable detailed error messages in production to prevent information leakage.
    // In production, set error reporting to minimal ini_set('display_errors', 0); ini_set('log_errors', 1);
  • Update Dependencies:
    • Keep PHP and all libraries updated to their latest versions to patch security vulnerabilities.
Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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