Files
USB-RAID-Array/Web/content/ftp/download.php
T
2026-10-18 15:55:34 +02:00

217 lines
9.2 KiB
PHP

<?php
require_once __DIR__ . '/../../includes/auth.php';
requireLogin('../../index.php');
requirePermission('downPer', 'You do not have permission to perform this operation.');
session_write_close();
set_time_limit(900); // 15 minutes max execution time
ob_start();
try {
require_once __DIR__ . '/../../config/config.php';
$logFile = __DIR__ . '/download_log.txt';
file_put_contents($logFile, "Download started: " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
$sftp = null;
try {
$sftp = initializeSFTP();
file_put_contents($logFile, "SFTP connection established\n", FILE_APPEND);
} catch (Exception $exception) {
file_put_contents($logFile, "SFTP connection failed: " . $exception->getMessage() . "\n", FILE_APPEND);
throw new Exception("Failed to connect to SFTP server: " . $exception->getMessage());
}
function zipFolderRecursive($sftp, $remoteBasePath, $currentPath, $zip, $logFile, &$temporaryFiles) {
file_put_contents($logFile, "Processing directory: $currentPath\n", FILE_APPEND);
$files = $sftp->nlist($currentPath);
if ($files === false) {
file_put_contents($logFile, "Failed to list directory contents for: $currentPath\n", FILE_APPEND);
throw new Exception("Failed to list directory contents for: $currentPath");
}
file_put_contents($logFile, "Found " . count($files) . " items in $currentPath\n", FILE_APPEND);
foreach ($files as $fileName) {
if ($fileName == '.' || $fileName == '..') continue;
$remotePath = rtrim($currentPath, '/') . '/' . $fileName;
$relativePath = substr($remotePath, strlen(rtrim(remoteDirname($remoteBasePath), '/')) + 1);
file_put_contents($logFile, "Processing: $remotePath (relative: $relativePath)\n", FILE_APPEND);
$isDirectory = $sftp->is_dir($remotePath);
if ($isDirectory) {
file_put_contents($logFile, "Found subdirectory: $remotePath\n", FILE_APPEND);
$zip->addEmptyDir($relativePath);
zipFolderRecursive($sftp, $remoteBasePath, $remotePath, $zip, $logFile, $temporaryFiles);
} else {
$temporaryFile = tempnam(sys_get_temp_dir(), 'sftp');
$temporaryFiles[] = $temporaryFile;
file_put_contents($logFile, "Downloading to temp file: $temporaryFile\n", FILE_APPEND);
$downloadStart = time();
$downloadSuccess = $sftp->get($remotePath, $temporaryFile);
$downloadTime = time() - $downloadStart;
if ($downloadSuccess) {
$fileSize = filesize($temporaryFile);
file_put_contents($logFile, "Download successful ($downloadTime seconds), size: $fileSize bytes\n", FILE_APPEND);
$zip->addFile($temporaryFile, $relativePath);
} else {
file_put_contents($logFile, "Failed to download file after $downloadTime seconds\n", FILE_APPEND);
}
}
}
}
function zipFolder($sftp, $folderPath, $zipFilePath, $logFile) {
file_put_contents($logFile, "Starting to zip folder recursively: $folderPath\n", FILE_APPEND);
$zip = new ZipArchive();
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
file_put_contents($logFile, "Failed to create zip archive\n", FILE_APPEND);
throw new Exception("Unable to create the zip file.");
}
$temporaryFiles = [];
try {
zipFolderRecursive($sftp, $folderPath, $folderPath, $zip, $logFile, $temporaryFiles);
file_put_contents($logFile, "Closing zip file\n", FILE_APPEND);
$zipSuccess = $zip->close();
foreach ($temporaryFiles as $temporaryFile) {
if (file_exists($temporaryFile)) {
@unlink($temporaryFile);
}
}
if ($zipSuccess) {
file_put_contents($logFile, "Zip created successfully, size: " . filesize($zipFilePath) . " bytes\n", FILE_APPEND);
return true;
} else {
file_put_contents($logFile, "Failed to create zip\n", FILE_APPEND);
return false;
}
} catch (Exception $exception) {
foreach ($temporaryFiles as $temporaryFile) {
if (file_exists($temporaryFile)) {
@unlink($temporaryFile);
}
}
file_put_contents($logFile, "Error during zip creation: " . $exception->getMessage() . "\n", FILE_APPEND);
throw $exception;
}
}
if (($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['file'])) ||
($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['file']))) {
$filePath = requireRemotePath($_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST['file'] : $_GET['file'], $defaultPath);
file_put_contents($logFile, "Requested file: $filePath\n", FILE_APPEND);
$fileExists = $sftp->file_exists($filePath);
$isDirectory = $sftp->is_dir($filePath);
file_put_contents($logFile, "File exists: " . ($fileExists ? "Yes" : "No") . "\n", FILE_APPEND);
file_put_contents($logFile, "Is directory: " . ($isDirectory ? "Yes" : "No") . "\n", FILE_APPEND);
if (!$fileExists && !$isDirectory) {
throw new Exception("File not found: $filePath");
}
if ($isDirectory) {
$zipFilePath = tempnam(sys_get_temp_dir(), 'folder_') . '.zip';
file_put_contents($logFile, "Creating zip at: $zipFilePath\n", FILE_APPEND);
if (zipFolder($sftp, $filePath, $zipFilePath, $logFile)) {
if (file_exists($zipFilePath) && filesize($zipFilePath) > 0) {
file_put_contents($logFile, "Sending zip file to browser, size: " . filesize($zipFilePath) . " bytes\n", FILE_APPEND);
while (ob_get_level()) {
ob_end_clean();
}
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '.zip"');
header('Content-Length: ' . filesize($zipFilePath));
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
readfile($zipFilePath);
file_put_contents($logFile, "Download completed\n", FILE_APPEND);
@unlink($zipFilePath);
exit;
} else {
throw new Exception("Failed to create zip file or zip file is empty");
}
} else {
throw new Exception("Failed to create zip archive");
}
} else {
$fileName = basename($filePath);
file_put_contents($logFile, "Downloading single file: $fileName\n", FILE_APPEND);
$temporaryFile = tempnam(sys_get_temp_dir(), 'file_');
$downloadStart = time();
$downloadSuccess = $sftp->get($filePath, $temporaryFile);
$downloadTime = time() - $downloadStart;
file_put_contents($logFile, "Download " . ($downloadSuccess ? "successful" : "failed") . " ($downloadTime seconds)\n", FILE_APPEND);
if ($downloadSuccess) {
$fileSize = filesize($temporaryFile);
file_put_contents($logFile, "Downloaded file size: $fileSize bytes\n", FILE_APPEND);
if ($fileSize > 0) {
while (ob_get_level()) {
ob_end_clean();
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . $fileSize);
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
readfile($temporaryFile);
file_put_contents($logFile, "Download completed\n", FILE_APPEND);
@unlink($temporaryFile);
exit;
} else {
@unlink($temporaryFile);
throw new Exception("Downloaded file is empty");
}
} else {
@unlink($temporaryFile);
throw new Exception("Failed to download file from SFTP server");
}
}
} else {
throw new Exception("Invalid request method or missing file parameter");
}
} catch (Exception $exception) {
$errorMessage = "Error: " . $exception->getMessage();
file_put_contents($logFile, $errorMessage . "\n", FILE_APPEND);
while (ob_get_level()) {
ob_end_clean();
}
header("HTTP/1.1 500 Internal Server Error");
echo $errorMessage;
}
?>