Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Universal File Converter</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .dropzone { | |
| border: 2px dashed #3b82f6; | |
| transition: all 0.3s ease; | |
| } | |
| .dropzone.active { | |
| border-color: #10b981; | |
| background-color: #f0f9ff; | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| .file-icon { | |
| font-size: 2rem; | |
| } | |
| .file-card:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| } | |
| .tooltip { | |
| visibility: hidden; | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .has-tooltip:hover .tooltip { | |
| visibility: visible; | |
| opacity: 1; | |
| } | |
| .download-options { | |
| max-height: 0; | |
| overflow: hidden; | |
| transition: max-height 0.3s ease-out; | |
| } | |
| .download-options.active { | |
| max-height: 300px; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <header class="text-center mb-10"> | |
| <h1 class="text-4xl font-bold text-blue-600 mb-2">Universal File Converter</h1> | |
| <p class="text-gray-600">Auto-detect file types and convert to your desired format</p> | |
| </header> | |
| <div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8"> | |
| <div id="dropzone" class="dropzone rounded-lg p-10 text-center cursor-pointer"> | |
| <div class="flex flex-col items-center justify-center"> | |
| <i class="fas fa-cloud-upload-alt text-blue-500 text-5xl mb-4"></i> | |
| <h3 class="text-xl font-semibold text-gray-700 mb-2">Drag & Drop files here</h3> | |
| <p class="text-gray-500 mb-4">or click to browse your files</p> | |
| <input type="file" id="fileInput" class="hidden" multiple> | |
| <button id="browseBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition duration-300"> | |
| Select Files | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="fileList" class="max-w-4xl mx-auto mb-8 hidden"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-4">Selected Files</h2> | |
| <div id="filesContainer" class="space-y-3"></div> | |
| </div> | |
| <div id="conversionOptions" class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8 hidden"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6">Conversion Options</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Output Format</label> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <button data-format="pdf" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-blue-100 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-pdf text-red-500 mr-2"></i> PDF | |
| </button> | |
| <button data-format="excel" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-green-100 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-excel text-green-600 mr-2"></i> Excel | |
| </button> | |
| <button data-format="word" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-blue-100 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-word text-blue-600 mr-2"></i> Word | |
| </button> | |
| <button data-format="xml" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-orange-100 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-code text-orange-500 mr-2"></i> XML | |
| </button> | |
| <button data-format="text" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-gray-200 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-alt text-gray-600 mr-2"></i> Text | |
| </button> | |
| <button data-format="csv" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-green-100 border border-gray-200 rounded-lg p-3 transition"> | |
| <i class="fas fa-file-csv text-green-700 mr-2"></i> CSV | |
| </button> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Options</label> | |
| <div class="space-y-3"> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="preserveLayout" class="rounded text-blue-600 mr-2"> | |
| <label for="preserveLayout">Preserve original layout</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="mergeFiles" class="rounded text-blue-600 mr-2"> | |
| <label for="mergeFiles">Merge all files into one</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="compressOutput" class="rounded text-blue-600 mr-2"> | |
| <label for="compressOutput">Compress output files</label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex justify-center"> | |
| <button id="convertBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-8 rounded-lg transition duration-300 flex items-center"> | |
| <i class="fas fa-exchange-alt mr-2"></i> Convert Files | |
| </button> | |
| </div> | |
| </div> | |
| <div id="progressSection" class="max-w-4xl mx-auto mb-8 hidden"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-4">Conversion Progress</h2> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden p-6"> | |
| <div id="progressContainer" class="space-y-4"></div> | |
| </div> | |
| </div> | |
| <div id="downloadSection" class="max-w-4xl mx-auto hidden"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-2xl font-semibold text-gray-800">Download Converted Files</h2> | |
| <button id="toggleDownloadOptions" class="text-blue-600 hover:text-blue-800 font-medium flex items-center"> | |
| <i class="fas fa-cog mr-2"></i> Download Options | |
| </button> | |
| </div> | |
| <div id="downloadOptions" class="download-options bg-white rounded-lg p-4 mb-4"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Download Quality</label> | |
| <select id="downloadQuality" class="w-full border border-gray-300 rounded-lg p-2"> | |
| <option value="high">High Quality (Recommended)</option> | |
| <option value="medium">Medium Quality</option> | |
| <option value="low">Low Quality (Smaller Size)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Download Method</label> | |
| <select id="downloadMethod" class="w-full border border-gray-300 rounded-lg p-2"> | |
| <option value="individual">Individual Files</option> | |
| <option value="zip">ZIP Archive</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="mt-4 flex justify-end"> | |
| <button id="applyDownloadOptions" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg"> | |
| Apply Options | |
| </button> | |
| </div> | |
| </div> | |
| <div id="downloadContainer" class="grid grid-cols-1 md:grid-cols-2 gap-4"></div> | |
| <div class="mt-6 flex justify-center"> | |
| <button id="downloadAllBtn" class="bg-green-600 hover:bg-green-700 text-white font-medium py-3 px-6 rounded-lg flex items-center"> | |
| <i class="fas fa-download mr-2"></i> Download All Files | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM elements | |
| const dropzone = document.getElementById('dropzone'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const browseBtn = document.getElementById('browseBtn'); | |
| const fileList = document.getElementById('fileList'); | |
| const filesContainer = document.getElementById('filesContainer'); | |
| const conversionOptions = document.getElementById('conversionOptions'); | |
| const convertBtn = document.getElementById('convertBtn'); | |
| const progressSection = document.getElementById('progressSection'); | |
| const progressContainer = document.getElementById('progressContainer'); | |
| const downloadSection = document.getElementById('downloadSection'); | |
| const downloadContainer = document.getElementById('downloadContainer'); | |
| const formatBtns = document.querySelectorAll('.format-btn'); | |
| const toggleDownloadOptions = document.getElementById('toggleDownloadOptions'); | |
| const downloadOptions = document.getElementById('downloadOptions'); | |
| const downloadAllBtn = document.getElementById('downloadAllBtn'); | |
| const applyDownloadOptions = document.getElementById('applyDownloadOptions'); | |
| let selectedFiles = []; | |
| let selectedFormat = null; | |
| let convertedFiles = []; | |
| let downloadQuality = 'high'; | |
| let downloadMethod = 'individual'; | |
| // Event listeners | |
| browseBtn.addEventListener('click', () => fileInput.click()); | |
| fileInput.addEventListener('change', handleFileSelect); | |
| // Drag and drop events | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, highlight, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, unhighlight, false); | |
| }); | |
| function highlight() { | |
| dropzone.classList.add('active'); | |
| } | |
| function unhighlight() { | |
| dropzone.classList.remove('active'); | |
| } | |
| dropzone.addEventListener('drop', handleDrop, false); | |
| // Format selection | |
| formatBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| formatBtns.forEach(b => b.classList.remove('border-blue-500', 'bg-blue-50')); | |
| this.classList.add('border-blue-500', 'bg-blue-50'); | |
| selectedFormat = this.getAttribute('data-format'); | |
| }); | |
| }); | |
| // Convert button | |
| convertBtn.addEventListener('click', startConversion); | |
| // Download options toggle | |
| toggleDownloadOptions.addEventListener('click', function() { | |
| downloadOptions.classList.toggle('active'); | |
| }); | |
| // Apply download options | |
| applyDownloadOptions.addEventListener('click', function() { | |
| downloadQuality = document.getElementById('downloadQuality').value; | |
| downloadMethod = document.getElementById('downloadMethod').value; | |
| showAlert('Download options updated successfully', 'success'); | |
| downloadOptions.classList.remove('active'); | |
| }); | |
| // Download all files | |
| downloadAllBtn.addEventListener('click', function() { | |
| if (downloadMethod === 'zip') { | |
| // Simulate downloading a ZIP archive | |
| const zipName = `converted_files_${new Date().getTime()}.zip`; | |
| showAlert(`Preparing ZIP archive: ${zipName}`, 'success'); | |
| // In a real app, this would trigger the actual ZIP download | |
| setTimeout(() => { | |
| showAlert(`Downloading ${zipName}`, 'success'); | |
| }, 1500); | |
| } else { | |
| // Simulate downloading all files individually | |
| showAlert('Starting download of all files', 'success'); | |
| // In a real app, this would trigger all individual downloads | |
| document.querySelectorAll('.download-btn').forEach(btn => { | |
| setTimeout(() => { | |
| btn.click(); | |
| }, 300); | |
| }); | |
| } | |
| }); | |
| // File handling functions | |
| function handleFileSelect(e) { | |
| const files = e.target.files || e.dataTransfer.files; | |
| processFiles(files); | |
| } | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| processFiles(files); | |
| } | |
| function processFiles(files) { | |
| selectedFiles = Array.from(files); | |
| if (selectedFiles.length > 0) { | |
| fileList.classList.remove('hidden'); | |
| conversionOptions.classList.remove('hidden'); | |
| filesContainer.innerHTML = ''; | |
| selectedFiles.forEach((file, index) => { | |
| const fileCard = createFileCard(file, index); | |
| filesContainer.appendChild(fileCard); | |
| }); | |
| } | |
| } | |
| function createFileCard(file, index) { | |
| const fileType = getFileType(file.name); | |
| const icon = getFileIcon(fileType); | |
| const fileSize = formatFileSize(file.size); | |
| const card = document.createElement('div'); | |
| card.className = 'file-card bg-white rounded-lg border border-gray-200 p-4 flex items-center justify-between transition duration-300'; | |
| card.innerHTML = ` | |
| <div class="flex items-center"> | |
| <div class="file-icon text-3xl mr-4 ${getFileIconColor(fileType)}"> | |
| ${icon} | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-gray-800 truncate max-w-xs">${file.name}</h3> | |
| <p class="text-sm text-gray-500">${fileType.toUpperCase()} • ${fileSize}</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <button class="remove-file-btn text-red-500 hover:text-red-700 p-2 rounded-full" data-index="${index}"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| `; | |
| // Add remove file functionality | |
| card.querySelector('.remove-file-btn').addEventListener('click', function() { | |
| const index = parseInt(this.getAttribute('data-index')); | |
| selectedFiles.splice(index, 1); | |
| if (selectedFiles.length === 0) { | |
| fileList.classList.add('hidden'); | |
| conversionOptions.classList.add('hidden'); | |
| } else { | |
| // Re-render file list | |
| filesContainer.innerHTML = ''; | |
| selectedFiles.forEach((file, idx) => { | |
| filesContainer.appendChild(createFileCard(file, idx)); | |
| }); | |
| } | |
| }); | |
| return card; | |
| } | |
| function getFileType(filename) { | |
| const extension = filename.split('.').pop().toLowerCase(); | |
| const fileTypes = { | |
| // Documents | |
| 'pdf': 'pdf', | |
| 'doc': 'word', | |
| 'docx': 'word', | |
| 'txt': 'text', | |
| 'rtf': 'text', | |
| 'odt': 'word', | |
| // Spreadsheets | |
| 'xls': 'excel', | |
| 'xlsx': 'excel', | |
| 'csv': 'csv', | |
| 'ods': 'excel', | |
| // Data | |
| 'xml': 'xml', | |
| 'json': 'json', | |
| // Images | |
| 'jpg': 'image', | |
| 'jpeg': 'image', | |
| 'png': 'image', | |
| 'gif': 'image', | |
| 'svg': 'image', | |
| 'webp': 'image', | |
| // Archives | |
| 'zip': 'archive', | |
| 'rar': 'archive', | |
| '7z': 'archive', | |
| 'tar': 'archive', | |
| 'gz': 'archive' | |
| }; | |
| return fileTypes[extension] || 'file'; | |
| } | |
| function getFileIcon(fileType) { | |
| const icons = { | |
| 'pdf': '<i class="fas fa-file-pdf"></i>', | |
| 'word': '<i class="fas fa-file-word"></i>', | |
| 'excel': '<i class="fas fa-file-excel"></i>', | |
| 'csv': '<i class="fas fa-file-csv"></i>', | |
| 'text': '<i class="fas fa-file-alt"></i>', | |
| 'xml': '<i class="fas fa-file-code"></i>', | |
| 'json': '<i class="fas fa-file-code"></i>', | |
| 'image': '<i class="fas fa-file-image"></i>', | |
| 'archive': '<i class="fas fa-file-archive"></i>', | |
| 'file': '<i class="fas fa-file"></i>' | |
| }; | |
| return icons[fileType] || icons['file']; | |
| } | |
| function getFileIconColor(fileType) { | |
| const colors = { | |
| 'pdf': 'text-red-500', | |
| 'word': 'text-blue-600', | |
| 'excel': 'text-green-600', | |
| 'csv': 'text-green-700', | |
| 'text': 'text-gray-600', | |
| 'xml': 'text-orange-500', | |
| 'json': 'text-yellow-500', | |
| 'image': 'text-purple-500', | |
| 'archive': 'text-yellow-600', | |
| 'file': 'text-gray-500' | |
| }; | |
| return colors[fileType] || colors['file']; | |
| } | |
| function formatFileSize(bytes) { | |
| if (bytes === 0) return '0 Bytes'; | |
| const k = 1024; | |
| const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; | |
| } | |
| // Conversion functions | |
| function startConversion() { | |
| if (!selectedFormat) { | |
| showAlert('Please select an output format', 'error'); | |
| return; | |
| } | |
| if (selectedFiles.length === 0) { | |
| showAlert('No files selected for conversion', 'error'); | |
| return; | |
| } | |
| // Show progress section | |
| progressSection.classList.remove('hidden'); | |
| progressContainer.innerHTML = ''; | |
| // Hide download section if shown | |
| downloadSection.classList.add('hidden'); | |
| // Reset converted files array | |
| convertedFiles = []; | |
| // Simulate conversion process | |
| selectedFiles.forEach((file, index) => { | |
| const progressItem = document.createElement('div'); | |
| progressItem.className = 'bg-gray-50 rounded-lg p-4'; | |
| progressItem.innerHTML = ` | |
| <div class="flex justify-between items-center mb-2"> | |
| <div class="flex items-center truncate"> | |
| <span class="font-medium text-gray-700 truncate max-w-xs">${file.name}</span> | |
| <div class="has-tooltip relative ml-2"> | |
| <i class="fas fa-info-circle text-blue-500"></i> | |
| <div class="tooltip absolute z-10 w-48 bg-gray-800 text-white text-xs rounded p-2 -left-24 -top-10"> | |
| Converting to ${selectedFormat.toUpperCase()} | |
| </div> | |
| </div> | |
| </div> | |
| <span class="text-sm font-medium text-gray-500" id="progressPercent-${index}">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="progressBar-${index}" class="progress-bar h-2.5 rounded-full bg-blue-600" style="width: 0%"></div> | |
| </div> | |
| `; | |
| progressContainer.appendChild(progressItem); | |
| // Simulate progress | |
| simulateConversionProgress(index, file); | |
| }); | |
| } | |
| function simulateConversionProgress(index, file) { | |
| let progress = 0; | |
| const interval = setInterval(() => { | |
| progress += Math.floor(Math.random() * 10) + 5; | |
| if (progress >= 100) { | |
| progress = 100; | |
| clearInterval(interval); | |
| // Store converted file info | |
| const originalName = file.name; | |
| const newName = originalName.substring(0, originalName.lastIndexOf('.')) + '.' + selectedFormat; | |
| convertedFiles.push({ | |
| originalName, | |
| newName, | |
| format: selectedFormat, | |
| size: Math.floor(file.size * (0.7 + Math.random() * 0.3)) // Random size for demo | |
| }); | |
| // When all files are converted | |
| if (convertedFiles.length === selectedFiles.length) { | |
| setTimeout(showDownloadOptions, 1000); | |
| } | |
| } | |
| document.getElementById(`progressBar-${index}`).style.width = `${progress}%`; | |
| document.getElementById(`progressPercent-${index}`).textContent = `${progress}%`; | |
| }, 200); | |
| } | |
| function showDownloadOptions() { | |
| downloadSection.classList.remove('hidden'); | |
| downloadContainer.innerHTML = ''; | |
| convertedFiles.forEach((file, index) => { | |
| const downloadCard = document.createElement('div'); | |
| downloadCard.className = 'bg-white rounded-lg border border-gray-200 p-4 flex items-center justify-between'; | |
| downloadCard.innerHTML = ` | |
| <div class="flex items-center truncate"> | |
| <div class="mr-3 text-2xl ${getFileIconColor(file.format)}"> | |
| ${getFileIcon(file.format)} | |
| </div> | |
| <div class="truncate"> | |
| <h3 class="font-medium text-gray-800 truncate">${file.newName}</h3> | |
| <p class="text-sm text-gray-500">${formatFileSize(file.size)} • From ${file.originalName}</p> | |
| </div> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button class="preview-btn text-blue-600 hover:text-blue-800 p-2 rounded-full" data-index="${index}"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| <button class="download-btn bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-300" data-index="${index}"> | |
| <i class="fas fa-download mr-2"></i> Download | |
| </button> | |
| </div> | |
| `; | |
| downloadContainer.appendChild(downloadCard); | |
| }); | |
| // Add preview functionality | |
| document.querySelectorAll('.preview-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const index = parseInt(this.getAttribute('data-index')); | |
| const file = convertedFiles[index]; | |
| showAlert(`Previewing ${file.newName} (simulated)`, 'success'); | |
| }); | |
| }); | |
| // Add download functionality | |
| document.querySelectorAll('.download-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const index = parseInt(this.getAttribute('data-index')); | |
| const file = convertedFiles[index]; | |
| // In a real app, this would download the actual converted file | |
| // Here we're just simulating the download | |
| showAlert(`Downloading ${file.newName} (${downloadQuality} quality)`, 'success'); | |
| }); | |
| }); | |
| } | |
| function showAlert(message, type) { | |
| const alert = document.createElement('div'); | |
| alert.className = `fixed top-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white font-medium ${ | |
| type === 'error' ? 'bg-red-500' : 'bg-green-500' | |
| }`; | |
| alert.textContent = message; | |
| document.body.appendChild(alert); | |
| setTimeout(() => { | |
| alert.classList.add('opacity-0', 'transition-opacity', 'duration-500'); | |
| setTimeout(() => alert.remove(), 500); | |
| }, 3000); | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=nkp/universefile" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |