Dear developers! Hello everyone, this is the file management system I built based on apache+ngin environment, with a total of 3 folders! If there is an improvement or a more perfect solution, can you share it with me? Thank you!
index.php
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Browser</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
h2 {
margin-top: 0;
}
table {
width: 80%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
a {
text-decoration: none;
color: #0645ad;
}
a:hover {
text-decoration: underline;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.highlight {
background-color: yellowgreen !important;
}
</style>
</head>
<body>
<h2>Root Directory:</h2>
<?php
// Get the current directory
$baseDir = __DIR__;
$currentDir = isset($_GET['dir']) && is_dir($baseDir . '/' . $_GET['dir'])
? realpath($baseDir . '/' . $_GET['dir'])
: $baseDir;
// Current path (as part of the URL)
$currentPath = isset($_GET['dir']) ? $_GET['dir'] : ''; // Not urlencoded for now
// Parent directory path
$parentPath = ''; // Initialize as an empty string
if ($currentPath !== '') {
$parentPath = dirname($currentPath);
// Remove any trailing slashes and ensure it does not return '.' as the parent path
if ($parentPath === '.') {
$parentPath = '';
} else {
$parentPath = urlencode($parentPath); // Now encode the parent path
}
}
// If the current directory is not the root directory, display the link to go back up
if ($currentDir !== $baseDir) {
// Use a relative path to build the link to go back up
echo '<a href="?dir=' . $parentPath . '">Go Back</a>';
}
// Function to format file size
function formatSize($bytes) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, 2) . ' ' . $units[$pow];
}
// Function to return emoji based on file extension
function getIcon($extension, $isFile) {
if ($isFile) {
switch ($extension) {
case 'jpg':
case 'jpeg':
case 'png':
case 'gif':
return 'πΌοΈ'; // Image
case 'zip':
case 'tar':
case 'gz':
case 'tgz':
return 'π¦'; // Compressed file
case 'txt':
case 'md':
case 'php':
case 'html':
case 'css':
case 'js':
return 'π'; // Text file
default:
return 'π'; // Other files
}
} else {
return 'π'; // Folder
}
}
// Display the file list
echo '<table>';
echo '<tr><th>Icon</th><th>Name</th><th>Last Modified Time</th><th>Size</th><th>Actions</th></tr>';
$files = new DirectoryIterator($currentDir);
foreach ($files as $file) {
// Check and skip hidden filenames
if ($file->isDot()) continue;
$isFile = $file->isFile();
$filename = $file->getFilename();
$encodedFilename = urlencode($filename); // Encode the filename once, for later use
$relativePath = $currentPath . ($currentPath !== '' ? '/' : '') . $filename;
$encodedRelativePath = urlencode($relativePath); // Encode the relative path once
$extension = $isFile ? strtolower($file->getExtension()) : '';
$size = $isFile ? formatSize($file->getSize()) : '-';
$lastModified = date('Y-m-d H:i:s', $file->getMTime());
$icon = getIcon($extension, $isFile);
// Set the base URL
$baseUrl = $isFile ? 'view.php?file=' : '?dir=';
$url = $baseUrl . $encodedRelativePath;
echo "<tr>";
echo "<td>" . $icon . "</td>";
echo "<td>";
if (!$isFile || !in_array($extension, ['zip', 'tar.gz'])) {
// For non-ZIP/tar.gz files, display the filename as a link
echo "<a href='" . htmlspecialchars($url) . "' " . ($isFile && in_array($extension, ['jpg', 'jpeg', 'png', 'gif']) ? 'target="_blank"' : '') . ">" . htmlspecialchars($filename) . "</a>";
} else {
// For ZIP/tar.gz files, display the filename and hint text, but do not link the filename
echo htmlspecialchars($filename) . " <span style='color:gray;'>(Please click Download on the right)</span>";
}
echo "</td>";
echo "<td>" . htmlspecialchars($lastModified) . "</td>";
echo "<td>" . htmlspecialchars($size) . "</td>";
echo "<td>";
if ($isFile) {
if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif'])) {
echo "<a href='view.php?file=" . $encodedFilename . "' target='_blank'>View</a>";
} elseif (in_array($extension, ['zip', 'tar.gz'])) {
echo "<a href='download.php?file=" . $encodedFilename . "' target='_blank'>Download</a>";
}
} else {
echo "<a href='?dir=" . $encodedFilename . "'>OPEN</a>";
}
echo "</td>";
echo "</tr>";
}
?>
</table>
<script>
// Highlight the selected table row
document.querySelectorAll('table tr').forEach(function(row) {
row.addEventListener('click', function() {
// Remove the highlight from previously highlighted rows
document.querySelectorAll('table tr.highlight').forEach(function(highlightedRow) {
highlightedRow.classList.remove('highlight');
});
// Add the highlight class to the current row
this.classList.add('highlight');
});
});
</script>
</body>
</html>
download.php
download.php
handles file download requests. It verifies whether the requested file exists in the allowed directory and provides the file to the user for download.
<?php
// download.php
$allowedDir = 'uploads/'; // Root directory allowed for downloads
if (isset($_GET['file'])) {
$requestedFile = $_GET['file'];
// Remove any path traversal characters
$requestedFile = str_replace(['..', '/', '\\'], '', $requestedFile);
// Check if the file exists within the uploads directory or its subdirectories
$found = false;
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($allowedDir));
foreach ($iterator as $file) {
if ($file->getFilename() === $requestedFile) {
$filePath = $file->getPathname();
$found = true;
break;
}
}
if ($found) {
if ($file->isFile() && $file->isReadable()) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $file->getSize());
ob_clean();
flush();
readfile($filePath);
exit;
} else {
header('HTTP/1.0 403 Forbidden');
echo "File is not readable or is not a file.";
}
} else {
header('HTTP/1.0 404 Not Found');
echo "File not found.";
}
} else {
header('HTTP/1.0 400 Bad Request');
echo "Error: No file specified.";
}
?>
view.php
view.php
is responsible for displaying the contents of viewable files such as images and documents in common formats. It sets the appropriate headers to ensure that the file is displayed inline in the browser.
<?php
// Set the allowed file directory for access (relative to the current script directory)
$allowedDir = 'uploads/';
// Check if the file has been sent via the GET parameter 'file'
if (isset($_GET['file'])) {
// Get and validate the filename
$file = basename(urldecode($_GET['file']));
$filePath = __DIR__ . DIRECTORY_SEPARATOR . $allowedDir . DIRECTORY_SEPARATOR . $file;
// Ensure the file is within the allowed directory and exists
if (file_exists($filePath) && strpos($filePath, __DIR__ . DIRECTORY_SEPARATOR . $allowedDir) === 0) {
// Get the file's MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);
// Decide to display the content or redirect to the download page based on the MIME type
switch ($mimeType) {
case 'image/jpeg':
case 'image/png':
case 'image/gif':
case 'application/pdf':
// Other document types that are supported for direct viewing can be added here
// Set the Content-Type header and output the file content
header('Content-Type: ' . $mimeType);
header('Content-Disposition: inline; filename="' . $file . '"');
readfile($filePath);
exit;
default:
// For unsupported file types that cannot be viewed directly, provide a download link
header('Location: download.php?file=' . urlencode($allowedDir . $file));
exit;
}
} else {
header('HTTP/1.0 404 Not Found');
echo "The file does not exist or the path is incorrect.";
}
} else {
header('HTTP/1.0 400 Bad Request');
echo "Error: No file specified.";
}
?>
Hereβs how it works
Save the three files in the root directory of the website. Create a new uploads folder. The function of this folder is that all your downloadable and viewable files are in this directory. Files in other root directories are not affected! . No .htaccess support is required
The files are located in the /public_html directory
- uploads
- Description: The directory that stores all downloadable and viewable files.
- download.php
- Function: Provides an interface for processing file download requests in the uploads folder.
- Description: When a user clicks a download link, this file will handle file retrieval and send HTTP responses.
- index.php
- Function: Serves as the main interface of the file browser.
- view.php
- Function: Used to view viewable files in the uploads folder. Supports file previews in formats such as images and common documents.