'No file uploaded']; } $file = $_FILES[$field_name]; // Check for upload errors if ($file['error'] !== UPLOAD_ERR_OK) { $upload_errors = [ UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize directive in php.ini', UPLOAD_ERR_FORM_SIZE => 'File exceeds MAX_FILE_SIZE directive in HTML form', UPLOAD_ERR_PARTIAL => 'File was only partially uploaded', UPLOAD_ERR_NO_FILE => 'No file was uploaded', UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder', UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk', UPLOAD_ERR_EXTENSION => 'File upload stopped by PHP extension' ]; return ['error' => $upload_errors[$file['error']] ?? 'Unknown upload error']; } // Check file size if ($file['size'] > $MAX_FILE_SIZE) { return ['error' => 'File is too large. Maximum size is ' . format_bytes($MAX_FILE_SIZE)]; } // Check file type $finfo = new finfo(FILEINFO_MIME_TYPE); $mime = $finfo->file($file['tmp_name']); if (!in_array($mime, $allowed_types)) { return ['error' => 'Invalid file type. Only PDF files are allowed']; } // Generate unique filename if (!is_dir($UPLOAD_DIR)) { mkdir($UPLOAD_DIR, 0755, true); } $filename = uniqid() . '.pdf'; $destination = $UPLOAD_DIR . $filename; if (!move_uploaded_file($file['tmp_name'], $destination)) { return ['error' => 'Failed to move uploaded file']; } return [ 'success' => true, 'filepath' => $destination, 'filename' => $filename, 'original_name' => $file['name'], 'size' => $file['size'] ]; } // Format bytes to human-readable format function format_bytes($bytes, $precision = 2) { $units = ['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, $precision) . ' ' . $units[$pow]; } // PDF Tools Functions function merge_pdfs($files, $output_filename) { $cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=" . escapeshellarg($output_filename) . " "; foreach ($files as $file) { $cmd .= escapeshellarg($file) . ' '; } exec($cmd, $output, $return_var); if ($return_var !== 0) { return ['error' => 'Failed to merge PDFs. Ghostscript error.']; } if (!file_exists($output_filename) || filesize($output_filename) === 0) { return ['error' => 'Merged PDF creation failed']; } return ['success' => true, 'filepath' => $output_filename]; } function split_pdf($filepath, $output_dir, $pages) { $output_files = []; foreach ($pages as $i => $page_range) { $output_file = $output_dir . 'split_' . ($i + 1) . '.pdf'; $cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dFirstPage={$page_range[0]} -dLastPage={$page_range[1]} -sOutputFile=" . escapeshellarg($output_file) . " " . escapeshellarg($filepath); exec($cmd, $output, $return_var); if ($return_var !== 0 || !file_exists($output_file)) { return ['error' => "Failed to split PDF at page range {$page_range[0]}-{$page_range[1]}"]; } $output_files[] = $output_file; } return ['success' => true, 'files' => $output_files]; } function pdf_to_images($filepath, $output_dir, $format = 'jpg', $dpi = 150) { $output_pattern = $output_dir . 'page_%d.' . $format; $device = $format === 'png' ? 'png16m' : 'jpeg'; $cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=$device -r$dpi -sOutputFile=" . escapeshellarg($output_pattern) . " " . escapeshellarg($filepath); exec($cmd, $output, $return_var); if ($return_var !== 0) { return ['error' => 'Failed to convert PDF to images']; } // Get list of generated images $images = glob($output_dir . 'page_*.' . $format); if (empty($images)) { return ['error' => 'No images were generated']; } sort($images); return ['success' => true, 'images' => $images]; } function compress_pdf($filepath, $output_file, $quality = 'ebook') { // Quality levels: screen (72dpi), ebook (150dpi), printer (300dpi), prepress (high quality) $cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/$quality -sOutputFile=" . escapeshellarg($output_file) . " " . escapeshellarg($filepath); exec($cmd, $output, $return_var); if ($return_var !== 0 || !file_exists($output_file)) { return ['error' => 'Failed to compress PDF']; } return ['success' => true, 'filepath' => $output_file]; } function protect_pdf($filepath, $output_file, $password) { $cmd = "qpdf --encrypt " . escapeshellarg($password) . " " . escapeshellarg($password) . " 256 -- " . escapeshellarg($filepath) . " " . escapeshellarg($output_file); exec($cmd, $output, $return_var); if ($return_var !== 0 || !file_exists($output_file)) { return ['error' => 'Failed to password protect PDF']; } return ['success' => true, 'filepath' => $output_file]; } function unlock_pdf($filepath, $output_file, $password) { $cmd = "qpdf --decrypt --password=" . escapeshellarg($password) . " " . escapeshellarg($filepath) . " " . escapeshellarg($output_file); exec($cmd, $output, $return_var); if ($return_var !== 0 || !file_exists($output_file)) { return ['error' => 'Failed to unlock PDF. Wrong password or corrupted file.']; } return ['success' => true, 'filepath' => $output_file]; } function pdf_to_text($filepath, $output_file) { $cmd = "pdftotext " . escapeshellarg($filepath) . " " . escapeshellarg($output_file); exec($cmd, $output, $return_var); if ($return_var !== 0 || !file_exists($output_file) || filesize($output_file) === 0) { return ['error' => 'Failed to extract text from PDF']; } return ['success' => true, 'filepath' => $output_file]; } function create_zip($files, $zip_filename) { $zip = new ZipArchive(); if ($zip->open($zip_filename, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) { return ['error' => 'Failed to create zip file']; } foreach ($files as $file) { if (file_exists($file)) { $zip->addFile($file, basename($file)); } } $zip->close(); if (!file_exists($zip_filename)) { return ['error' => 'Zip file creation failed']; } return ['success' => true, 'filepath' => $zip_filename]; } // Clean up old files function cleanup_old_files() { global $UPLOAD_DIR, $FILE_LIFETIME; $files = glob($UPLOAD_DIR . '*'); $now = time(); foreach ($files as $file) { if (is_file($file) && ($now - filemtime($file) > $FILE_LIFETIME)) { if (is_dir($file)) { array_map('unlink', glob("$file/*")); rmdir($file); } else { unlink($file); } } } } // Main processing session_start(); cleanup_old_files(); $errors = check_requirements(); $action = $_GET['action'] ?? ''; $result = null; $download_link = ''; $original_filename = ''; // Process actions if (empty($errors)) { switch ($action) { case 'merge': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $files = []; $upload_errors = []; foreach ($_FILES['pdf_files']['tmp_name'] as $i => $tmp_name) { if ($_FILES['pdf_files']['error'][$i] === UPLOAD_ERR_OK) { $upload = handle_upload('pdf_files'); if (isset($upload['filepath'])) { $files[] = $upload['filepath']; if ($i === 0) $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); } else { $upload_errors[] = $upload['error']; } } } if (count($files) > 1) { $output_file = $UPLOAD_DIR . 'merged_' . uniqid() . '.pdf'; $result = merge_pdfs($files, $output_file); if (isset($result['filepath'])) { $download_link = $result['filepath']; $original_filename = $original_filename ? $original_filename . '_merged' : 'merged'; } } else { $result = ['error' => 'You need to upload at least 2 PDF files to merge']; } if (!empty($upload_errors)) { $result['upload_errors'] = $upload_errors; } } break; case 'split': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $page_ranges = []; $ranges = explode(',', $_POST['page_ranges']); foreach ($ranges as $range) { $parts = explode('-', trim($range)); if (count($parts) === 1) { $page_ranges[] = [$parts[0], $parts[0]]; } else { $page_ranges[] = [$parts[0], $parts[1] ?? $parts[0]]; } } $output_dir = $UPLOAD_DIR . 'split_' . uniqid() . '/'; mkdir($output_dir, 0755, true); $result = split_pdf($upload['filepath'], $output_dir, $page_ranges); if (isset($result['files'])) { $zip_filename = $UPLOAD_DIR . 'split_' . uniqid() . '.zip'; $zip_result = create_zip($result['files'], $zip_filename); if (isset($zip_result['filepath'])) { $download_link = $zip_result['filepath']; $original_filename = $original_filename ? $original_filename . '_split' : 'split'; } else { $result = $zip_result; } } } else { $result = $upload; } } break; case 'pdf_to_jpg': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $output_dir = $UPLOAD_DIR . 'images_' . uniqid() . '/'; mkdir($output_dir, 0755, true); $format = $_POST['format'] ?? 'jpg'; $dpi = min(max(intval($_POST['dpi'] ?? 150), 300, 72); $result = pdf_to_images($upload['filepath'], $output_dir, $format, $dpi); if (isset($result['images'])) { $zip_filename = $UPLOAD_DIR . 'images_' . uniqid() . '.zip'; $zip_result = create_zip($result['images'], $zip_filename); if (isset($zip_result['filepath'])) { $download_link = $zip_result['filepath']; $original_filename = $original_filename ? $original_filename . '_images' : 'images'; } else { $result = $zip_result; } } } else { $result = $upload; } } break; case 'compress': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $quality = $_POST['quality'] ?? 'ebook'; $output_file = $UPLOAD_DIR . 'compressed_' . uniqid() . '.pdf'; $result = compress_pdf($upload['filepath'], $output_file, $quality); if (isset($result['filepath'])) { $download_link = $result['filepath']; $original_filename = $original_filename ? $original_filename . '_compressed' : 'compressed'; } } else { $result = $upload; } } break; case 'protect': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $password = $_POST['password'] ?? ''; if (empty($password)) { $result = ['error' => 'Password is required']; } else { $output_file = $UPLOAD_DIR . 'protected_' . uniqid() . '.pdf'; $result = protect_pdf($upload['filepath'], $output_file, $password); if (isset($result['filepath'])) { $download_link = $result['filepath']; $original_filename = $original_filename ? $original_filename . '_protected' : 'protected'; } } } else { $result = $upload; } } break; case 'unlock': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $password = $_POST['password'] ?? ''; if (empty($password)) { $result = ['error' => 'Password is required']; } else { $output_file = $UPLOAD_DIR . 'unlocked_' . uniqid() . '.pdf'; $result = unlock_pdf($upload['filepath'], $output_file, $password); if (isset($result['filepath'])) { $download_link = $result['filepath']; $original_filename = $original_filename ? $original_filename . '_unlocked' : 'unlocked'; } } } else { $result = $upload; } } break; case 'pdf_to_text': if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload = handle_upload('pdf_file'); if (isset($upload['filepath'])) { $original_filename = pathinfo($upload['original_name'], PATHINFO_FILENAME); $output_file = $UPLOAD_DIR . 'text_' . uniqid() . '.txt'; $result = pdf_to_text($upload['filepath'], $output_file); if (isset($result['filepath'])) { $download_link = $result['filepath']; $original_filename = $original_filename ? $original_filename . '_text' : 'text'; } } else { $result = $upload; } } break; } } // HTML Interface ?>
Merge, split, compress, convert and more - 100% free and easy to use. No installation or registration required.
Get StartedPlease contact your hosting provider to resolve these issues.
Select the tool you need to work with your PDF files
Select multiple PDF files to merge them into a single document.
Upload a PDF file and specify page ranges to split (e.g., "1-3,5,7-9").
Convert each page of your PDF to JPG or PNG images.
Reduce the file size of your PDF document.
Add password protection to your PDF file.
Remove password protection from a PDF file.
Extract text from your PDF document.
We provide the best PDF tools with these amazing features
Your files are processed securely and deleted automatically after 1 hour. We don't store your documents permanently.
Our tools use optimized algorithms to process your PDF files as quickly as possible, saving you time.
All tools work directly in your browser. No software installation or registration required.
All our PDF tools are completely free to use with no hidden charges or limitations.
Works perfectly on all devices including smartphones and tablets.
Use our tools as many times as you need without any restrictions.