btg-sandbox-video-upscaler/uploader.php
DJP d49ecf1527 Add automatic file cleanup for uploads directory
- Created FileCleanup utility class to manage old upload files
- Automatically removes files older than 24 hours on each request
- Added cleanup calls to both estimate.php and uploader.php processes
- Includes detailed logging and statistics for cleanup operations
- Provides formatBytes utility for human-readable file size reporting
- Includes directory statistics functionality for monitoring

This prevents the uploads directory from growing indefinitely and ensures
proper disk space management for the video processing system.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 14:43:03 -04:00

153 lines
No EOL
5.8 KiB
PHP

<?php
require_once 'cleanup.php';
// Prevent duplicate class definition
if (!class_exists('VideoUploader')) {
class VideoUploader {
private $apiClient;
public function __construct($apiClient) {
$this->apiClient = $apiClient;
}
public function processUpload($file) {
// Clean up old files first (older than 24 hours)
Logger::log('Starting automatic cleanup of old upload files');
$cleanupStats = FileCleanup::cleanupOldFiles(24, 'uploads/');
if ($cleanupStats['files_deleted'] > 0) {
Logger::log("Cleanup completed: {$cleanupStats['files_deleted']} old files removed, " .
FileCleanup::formatBytes($cleanupStats['bytes_freed']) . " freed");
}
Logger::log('Starting video upload process');
Logger::log('File info: ' . print_r($file, true));
if (!isset($file['tmp_name']) || !file_exists($file['tmp_name'])) {
throw new Exception('Invalid file data or file not found');
}
// Get video information from session
if (!isset($_SESSION['video_request']['info'])) {
throw new Exception('Video request information not found in session');
}
$videoInfo = $_SESSION['video_request']['info'];
Logger::log('Using video info: ' . json_encode($videoInfo));
// Accept the request and get upload URLs
$requestId = $_SESSION['video_request']['requestId'] ?? null;
if (!$requestId) {
throw new Exception('Request ID not found in session');
}
Logger::log("Accepting request ID: $requestId");
$acceptResponse = $this->apiClient->acceptVideoRequest($requestId);
Logger::log('Accept response: ' . json_encode($acceptResponse));
if (!isset($acceptResponse['urls']) || !is_array($acceptResponse['urls'])) {
throw new Exception('Invalid upload URLs received from API');
}
$uploadUrls = $acceptResponse['urls'];
$uploadId = $acceptResponse['uploadId'] ?? null;
// Upload file parts
$uploadResults = $this->uploadParts($file, $uploadUrls);
// Complete the upload
$this->apiClient->completeUpload($requestId, $uploadResults);
Logger::log('Upload completed successfully');
return $requestId;
}
private function uploadParts($file, $urls) {
$results = [];
$fileSize = filesize($file['tmp_name']);
$partSize = ceil($fileSize / count($urls));
Logger::log("Uploading file parts. Total size: $fileSize, Part size: $partSize");
foreach ($urls as $index => $url) {
$partNum = $index + 1;
$start = $index * $partSize;
$length = min($partSize, $fileSize - $start);
Logger::log("Uploading part $partNum. Start: $start, Length: $length");
// Upload the part and get ETag
$eTag = $this->uploadFilePart($file['tmp_name'], $url, $start, $length);
$results[] = [
'partNum' => $partNum,
'eTag' => $eTag
];
Logger::log("Uploaded part $partNum with ETag: $eTag");
}
return $results;
}
private function uploadFilePart($filePath, $url, $start, $length) {
Logger::log("Uploading file part to URL: $url");
$handle = fopen($filePath, 'rb');
if (!$handle) {
throw new Exception('Could not open file for reading');
}
// Seek to the start position
fseek($handle, $start);
// Read the chunk
$data = fread($handle, $length);
fclose($handle);
if ($data === false) {
throw new Exception('Failed to read file chunk');
}
// Create curl handle
$ch = curl_init($url);
// Setup curl options
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => false,
CURLOPT_HTTPHEADER => [
'Content-Type: application/octet-stream',
'Content-Length: ' . strlen($data)
]
]);
// Execute the request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode !== 200) {
Logger::log("Upload failed with HTTP code $httpCode. Response: $response", 'ERROR');
throw new Exception("Failed to upload file part. HTTP Code: $httpCode");
}
// Extract ETag from headers
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
preg_match('/ETag: "(.*?)"/', $headers, $matches);
$eTag = $matches[1] ?? null;
curl_close($ch);
if (!$eTag) {
throw new Exception('No ETag received from upload');
}
Logger::log("Successfully uploaded part. ETag: $eTag");
return $eTag;
}
}
}
?>