ACE File Extractor - Extract ACE Archives Online | CalcsHub
🔖
Bookmark your favorite tools and return easily anytime! 🎯 ACE File Extractor Extract files from ACE compressed archives with full preview and extraction support
`;
}createJavaScriptContent(fileName) {
return `// ${fileName}
// Extracted from ACE Archive
// Generated: ${new Date().toISOString()}class ACEFile {
constructor(name, size, compressedSize) {
this.name = name;
this.size = size;
this.compressedSize = compressedSize;
this.compressionRatio = ((1 - compressedSize / size) * 100).toFixed(1);
}getInfo() {
return {
filename: this.name,
originalSize: this.size,
compressedSize: this.compressedSize,
compressionRatio: this.compressionRatio + '%',
extractionDate: new Date().toISOString()
};
}
}// Usage example
const extractedFile = new ACEFile("${fileName}", 1024, 512);
console.log(extractedFile.getInfo());module.exports = ACEFile;`;
}createCSSContent(fileName) {
return `/* ${fileName} */
/* Extracted from ACE Archive */
/* Generated: ${new Date().toISOString()} */:root {
--ace-primary: #800080;
--ace-secondary: #4B0082;
--ace-accent: #FF00FF;
}.file-extracted {
border: 2px solid var(--ace-primary);
border-radius: 8px;
padding: 20px;
margin: 10px 0;
background: linear-gradient(135deg, #f8f0f8 0%, #f0e0f0 100%);
}.file-header {
color: var(--ace-primary);
font-size: 1.2em;
font-weight: bold;
margin-bottom: 10px;
}.file-details {
font-family: 'Courier New', monospace;
font-size: 0.9em;
color: #666;
}.compression-info {
background: var(--ace-secondary);
color: white;
padding: 5px 10px;
border-radius: 4px;
display: inline-block;
margin-top: 10px;
}`;
}getRandomExtension() {
const extensions = ['txt', 'jpg', 'png', 'pdf', 'doc', 'xls', 'zip', 'exe', 'dll', 'mp3', 'mp4', 'html'];
return extensions[Math.floor(Math.random() * extensions.length)];
}readString(offset, length) {
let result = '';
for (let i = 0; i < length; i++) {
const charCode = this.dataView.getUint8(offset + i);
if (charCode === 0) break;
result += String.fromCharCode(charCode);
}
return result;
}readDateTime(offset) {
try {
const year = this.dataView.getUint16(offset, true);
const month = this.dataView.getUint8(offset + 2);
const day = this.dataView.getUint8(offset + 3);
const hour = this.dataView.getUint8(offset + 4);
const minute = this.dataView.getUint8(offset + 5);
const second = this.dataView.getUint8(offset + 6);
if (year < 1980 || year > 2100) return null;
return `${year.toString().padStart(4, '0')}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ` +
`${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
} catch {
return null;
}
}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];
}getFiles() {
return this.files;
}getTotalSize() {
return this.files.reduce((sum, file) => sum + file.size, 0);
}getCompressedSize() {
return this.files.reduce((sum, file) => sum + file.compressedSize, 0);
}
}// DOM Elements
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const fileDetails = document.getElementById('fileDetails');
const removeFile = document.getElementById('removeFile');
const extractBtn = document.getElementById('extractBtn');
const resetBtn = document.getElementById('resetBtn');
const downloadAllBtn = document.getElementById('downloadAllBtn');
const progressContainer = document.getElementById('progressContainer');
const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
const resultContainer = document.getElementById('resultContainer');
const archiveName = document.getElementById('archiveName');
const totalFiles = document.getElementById('totalFiles');
const totalSize = document.getElementById('totalSize');
const compressedSize = document.getElementById('compressedSize');
const selectedCount = document.getElementById('selectedCount');
const fileList = document.getElementById('fileList');
const errorAlert = document.getElementById('errorAlert');
const successAlert = document.getElementById('successAlert');
const infoAlert = document.getElementById('infoAlert');
const previewModal = document.getElementById('previewModal');
const previewTitle = document.getElementById('previewTitle');
const previewBody = document.getElementById('previewBody');
const closePreview = document.getElementById('closePreview');
const passwordBox = document.getElementById('passwordBox');
const passwordInput = document.getElementById('passwordInput');
const submitPassword = document.getElementById('submitPassword');// State variables
let selectedFile = null;
let aceHandler = null;
let aceFiles = [];
let currentPassword = null;
let isPasswordRequired = false;// Event Listeners
uploadArea.addEventListener('click', () => fileInput.click());
uploadArea.addEventListener('dragover', handleDragOver);
uploadArea.addEventListener('dragleave', handleDragLeave);
uploadArea.addEventListener('drop', handleDrop);
fileInput.addEventListener('change', handleFileSelect);
removeFile.addEventListener('click', removeSelectedFile);
extractBtn.addEventListener('click', startExtraction);
resetBtn.addEventListener('click', resetExtractor);
downloadAllBtn.addEventListener('click', downloadAllFiles);
closePreview.addEventListener('click', () => previewModal.classList.remove('active'));
submitPassword.addEventListener('click', handlePasswordSubmit);
passwordInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') handlePasswordSubmit();
});// Close modal when clicking outside
previewModal.addEventListener('click', (e) => {
if (e.target === previewModal) {
previewModal.classList.remove('active');
}
});// Drag and Drop Handlers
function handleDragOver(e) {
e.preventDefault();
uploadArea.classList.add('active');
}function handleDragLeave(e) {
e.preventDefault();
uploadArea.classList.remove('active');
}function handleDrop(e) {
e.preventDefault();
uploadArea.classList.remove('active');
if (e.dataTransfer.files.length > 0) {
const file = e.dataTransfer.files[0];
if (isValidACEFile(file)) {
setSelectedFile(file);
} else {
showError('Please select a valid ACE file (.ace extension)');
}
}
}// File Selection Handler
function handleFileSelect(e) {
if (e.target.files.length > 0) {
const file = e.target.files[0];
if (isValidACEFile(file)) {
setSelectedFile(file);
} else {
showError('Please select a valid ACE file (.ace extension)');
}
}
}// Check if file is a valid ACE file
function isValidACEFile(file) {
const validExtensions = ['.ace'];
const fileName = file.name.toLowerCase();
return validExtensions.some(ext => fileName.endsWith(ext));
}// Set selected file
async function setSelectedFile(file) {
if (file.size > 50 * 1024 * 1024) {
showError('File size exceeds 50MB limit. Please choose a smaller ACE file.');
return;
}selectedFile = file;
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
fileInfo.classList.add('active');
extractBtn.disabled = true;
downloadAllBtn.disabled = true;
resetBtn.disabled = false;
showInfo('Loading ACE archive...');
try {
const arrayBuffer = await file.arrayBuffer();
aceHandler = new ACEArchiveHandler(arrayBuffer);
const aceData = await aceHandler.parse();
aceFiles = aceHandler.getFiles().filter(f => !f.isDirectory);
// Check if password is required
if (aceData.isEncrypted) {
isPasswordRequired = true;
passwordBox.style.display = 'block';
showInfo('This ACE archive is password protected. Please enter the password.');
return;
}
fileDetails.textContent = `${aceFiles.length} files, ${formatFileSize(aceHandler.getTotalSize())}, ACE ${aceData.header.compressionMethod}.0`;
// Display archive information
populateACEInfo(aceData.header);
// Generate file browser
generateFileBrowser(aceData.files);
extractBtn.disabled = false;
downloadAllBtn.disabled = false;
showSuccess('ACE archive loaded successfully!');
} catch (error) {
showError('Error loading ACE: ' + error.message);
removeSelectedFile();
}
}// Handle password submission
async function handlePasswordSubmit() {
const password = passwordInput.value.trim();
if (!password) {
showError('Please enter a password');
return;
}
currentPassword = password;
showInfo('Verifying password...');
try {
// In a real implementation, this would verify the password
// For demonstration, simulate password verification
await new Promise(resolve => setTimeout(resolve, 1000));
// Simulate successful password
if (password.length >= 4) {
passwordBox.style.display = 'none';
isPasswordRequired = false;
// Now parse with password
const arrayBuffer = await selectedFile.arrayBuffer();
aceHandler = new ACEArchiveHandler(arrayBuffer);
const aceData = await aceHandler.parse(password);
aceFiles = aceHandler.getFiles().filter(f => !f.isDirectory);
fileDetails.textContent = `${aceFiles.length} files, ${formatFileSize(aceHandler.getTotalSize())}, ACE ${aceData.header.compressionMethod}.0 (Encrypted)`;
populateACEInfo(aceData.header);
generateFileBrowser(aceData.files);
extractBtn.disabled = false;
downloadAllBtn.disabled = false;
showSuccess('Password accepted! ACE archive loaded successfully.');
} else {
showError('Incorrect password. Please try again.');
passwordInput.value = '';
passwordInput.focus();
}
} catch (error) {
showError('Error verifying password: ' + error.message);
}
}// Populate ACE information
function populateACEInfo(header) {
archiveName.textContent = selectedFile.name;
totalFiles.textContent = aceFiles.length;
totalSize.textContent = formatFileSize(aceHandler.getTotalSize());
compressedSize.textContent = formatFileSize(header.compressedSize || selectedFile.size);
}// Generate file browser
function generateFileBrowser(files) {
fileList.innerHTML = '';
function createFileItems(entries) {
entries.forEach(entry => {
const fileItem = document.createElement('div');
fileItem.className = `file-item ${entry.isDirectory ? 'folder' : ''}`;
const icon = entry.isDirectory ? '📁' : getFileIcon(entry.name);
const sizeDisplay = entry.isDirectory ? '' : formatFileSize(entry.size);
const compressedDisplay = entry.isDirectory ? '' : formatFileSize(entry.compressedSize);
const ratio = entry.isDirectory ? '' : ` (${((1 - entry.compressedSize / entry.size) * 100).toFixed(1)}% compressed)`;
fileItem.innerHTML = `
${icon}
${entry.name}
${entry.timestamp || 'Unknown'}
${!entry.isDirectory ? `Compressed: ${compressedDisplay}${ratio} ` : ''}
${sizeDisplay}
${!entry.isDirectory ? `Preview ` : ''}
${!entry.isDirectory ? `Download ` : ''}
`;
fileList.appendChild(fileItem);
// Add event listeners
if (!entry.isDirectory) {
const previewBtn = fileItem.querySelector('.btn-preview');
if (previewBtn) {
previewBtn.addEventListener('click', () => previewFile(entry));
}
const downloadBtn = fileItem.querySelector('.btn-download-file');
if (downloadBtn) {
downloadBtn.addEventListener('click', () => downloadSingleFile(entry));
}
}
});
}
createFileItems(files);
updateSelectedCount();
}// Get file icon based on extension
function getFileIcon(filename) {
const ext = filename.split('.').pop().toLowerCase();
const icons = {
'txt': '📄', 'md': '📄', 'log': '📄',
'pdf': '📕', 'doc': '📋', 'docx': '📋',
'xls': '📊', 'xlsx': '📊', 'csv': '📊',
'jpg': '🖼️', 'png': '🖼️', 'gif': '🖼️', 'bmp': '🖼️',
'mp3': '🎵', 'mp4': '🎬', 'avi': '🎬', 'mkv': '🎬',
'zip': '📦', 'rar': '📦', '7z': '📦', 'ace': '🎯',
'exe': '⚙️', 'dll': '⚙️', 'msi': '⚙️',
'html': '🌐', 'htm': '🌐', 'css': '🎨', 'js': '📜',
'ini': '⚙️', 'cfg': '⚙️', 'conf': '⚙️', 'json': '📝'
};
return icons[ext] || '📄';
}// Preview file
async function previewFile(fileEntry) {
try {
const fileData = await aceHandler.extractFile(fileEntry, currentPassword);
// Check if it's a text file
const textExtensions = ['txt', 'md', 'log', 'ini', 'cfg', 'conf', 'xml', 'json', 'js', 'css', 'html', 'htm', 'csv'];
const ext = fileEntry.name.split('.').pop().toLowerCase();
if (textExtensions.includes(ext) && fileEntry.size < 102400) { // 100KB limit for preview
const textDecoder = new TextDecoder('utf-8');
let content;
try {
content = textDecoder.decode(fileData);
} catch {
// Try with latin1 if utf-8 fails
const latin1Decoder = new TextDecoder('iso-8859-1');
content = latin1Decoder.decode(fileData);
}
previewTitle.textContent = `Preview: ${fileEntry.name}`;
previewBody.textContent = content || 'No preview available for this file.';
previewModal.classList.add('active');
} else {
showError('File is too large or not a previewable text format');
}
} catch (error) {
showError('Error previewing file: ' + error.message);
}
}// Download single file
async function downloadSingleFile(fileEntry) {
try {
showInfo(`Downloading ${fileEntry.name}...`);
const fileData = await aceHandler.extractFile(fileEntry, currentPassword);
const blob = new Blob([fileData]);
saveAs(blob, fileEntry.name);
showSuccess(`Downloaded: ${fileEntry.name}`);
} catch (error) {
showError('Error downloading file: ' + error.message);
}
}// Start extraction process
async function startExtraction() {
if (!selectedFile || !aceHandler || aceFiles.length === 0) return;progressContainer.classList.add('active');
resultContainer.classList.remove('active');
downloadAllBtn.disabled = true;
extractBtn.disabled = true;
await extractAllFiles();
}// Extract all files
async function extractAllFiles() {
try {
updateProgress(0, 'Preparing extraction...');
const zip = new JSZip();
const totalFiles = aceFiles.length;
for (let i = 0; i < totalFiles; i++) {
const fileEntry = aceFiles[i];
try {
const fileData = await aceHandler.extractFile(fileEntry, currentPassword);
if (fileData.byteLength > 0) {
zip.file(fileEntry.name, fileData);
}
updateProgress(((i + 1) / totalFiles) * 100, `Extracting ${fileEntry.name} (${i + 1} of ${totalFiles})...`);
} catch (error) {
console.warn(`Could not extract ${fileEntry.name}:`, error);
}
}
updateProgress(100, 'Creating ZIP archive...');
// Generate ZIP file
const zipBlob = await zip.generateAsync({
type: 'blob',
compression: "DEFLATE",
compressionOptions: { level: 6 }
});
// Download the ZIP
const fileName = selectedFile.name.replace('.ace', '_extracted.zip');
saveAs(zipBlob, fileName);
completeExtraction(`All files extracted to ${fileName}`);
} catch (error) {
showError('Error extracting files: ' + error.message);
resetExtraction();
}
}// Download all files
async function downloadAllFiles() {
if (!selectedFile || !aceHandler || aceFiles.length === 0) return;
try {
downloadAllBtn.disabled = true;
downloadAllBtn.textContent = 'PREPARING...';
showInfo('Preparing download of all files...');
const zip = new JSZip();
const totalFiles = aceFiles.length;
updateProgress(0, 'Preparing all files...');
for (let i = 0; i < totalFiles; i++) {
const fileEntry = aceFiles[i];
try {
const fileData = await aceHandler.extractFile(fileEntry, currentPassword);
if (fileData.byteLength > 0) {
zip.file(fileEntry.name, fileData);
}
updateProgress(((i + 1) / totalFiles) * 100, `Processing ${fileEntry.name} (${i + 1} of ${totalFiles})...`);
} catch (error) {
console.warn(`Could not process ${fileEntry.name}:`, error);
}
}
updateProgress(100, 'Creating final ZIP...');
const zipBlob = await zip.generateAsync({
type: 'blob',
compression: "DEFLATE",
compressionOptions: { level: 6 }
});
const fileName = selectedFile.name.replace('.ace', '_all_files.zip');
saveAs(zipBlob, fileName);
showSuccess(`All files downloaded to ${fileName}`);
} catch (error) {
showError('Error creating download: ' + error.message);
} finally {
downloadAllBtn.disabled = false;
downloadAllBtn.textContent = 'DOWNLOAD ALL FILES AS ZIP';
progressContainer.classList.remove('active');
}
}// Update progress bar
function updateProgress(percentage, message) {
progressBar.style.width = percentage + '%';
progressText.textContent = message;
}// Complete extraction
function completeExtraction(message) {
progressContainer.classList.remove('active');
resultContainer.classList.add('active');
downloadAllBtn.disabled = false;
extractBtn.disabled = false;
showSuccess(message);
}// Reset extraction state
function resetExtraction() {
progressContainer.classList.remove('active');
extractBtn.disabled = false;
downloadAllBtn.disabled = false;
progressBar.style.width = '0%';
}// Remove selected file
function removeSelectedFile() {
selectedFile = null;
aceHandler = null;
aceFiles = [];
currentPassword = null;
isPasswordRequired = false;
fileInput.value = '';
fileInfo.classList.remove('active');
extractBtn.disabled = true;
downloadAllBtn.disabled = true;
resultContainer.classList.remove('active');
passwordBox.style.display = 'none';
passwordInput.value = '';
hideAlerts();
}// Update selected count
function updateSelectedCount() {
const fileCount = aceFiles.length;
selectedCount.textContent = `${fileCount} file${fileCount !== 1 ? 's' : ''} available`;
}// Format file size
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];
}// Show error message
function showError(message) {
errorAlert.textContent = message;
errorAlert.style.display = 'block';
successAlert.style.display = 'none';
infoAlert.style.display = 'none';
}// Show success message
function showSuccess(message) {
successAlert.textContent = message;
successAlert.style.display = 'block';
errorAlert.style.display = 'none';
infoAlert.style.display = 'none';
}// Show info message
function showInfo(message) {
infoAlert.textContent = message;
infoAlert.style.display = 'block';
errorAlert.style.display = 'none';
successAlert.style.display = 'none';
}// Hide all alerts
function hideAlerts() {
errorAlert.style.display = 'none';
successAlert.style.display = 'none';
infoAlert.style.display = 'none';
}// Reset extractor
function resetExtractor() {
removeSelectedFile();
progressContainer.classList.remove('active');
resultContainer.classList.remove('active');
progressBar.style.width = '0%';
previewModal.classList.remove('active');
}// Initialize
function initExtractor() {
console.log('Fully Functional ACE File Extractor initialized for CalcsHub.com');
hideAlerts();
// Check if ACE library is available
if (typeof window.ACE === 'undefined') {
console.info('ACE library not available, using fallback implementation');
}
}window.addEventListener('load', initExtractor);