ExchangeNow adlı üyeden alıntı: mesajı görüntüle
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Profesyonel PDF Dönüştürücü</title>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
    
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">

    <style>
        :root {
            --primary-color: #4f46e5;
            --primary-hover: #4338ca;
            --bg-color: #f3f4f6;
            --card-bg: #ffffff;
            --text-main: #111827;
            --text-muted: #6b7280;
            --border-color: #e5e7eb;
        }

        * { box-sizing: border-box; margin: 0; padding: 0; }

        body {
            font-family: 'Inter', sans-serif;
            background-color: var(--bg-color);
            color: var(--text-main);
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }

        .card {
            background-color: var(--card-bg);
            width: 100%;
            max-width: 550px;
            padding: 2rem;
            border-radius: 16px;
            box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
        }

        h2 { text-align: center; margin-bottom: 0.5rem; font-weight: 600; }
        p.subtitle { text-align: center; color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem; }

        .drop-zone {
            border: 2px dashed #cbd5e1;
            border-radius: 12px;
            padding: 2.5rem 1.5rem;
            cursor: pointer;
            text-align: center;
            transition: all 0.2s ease;
            background-color: #f8fafc;
            margin-bottom: 1rem;
        }

        .drop-zone:hover, .drop-zone.dragover { border-color: var(--primary-color); background-color: #eef2ff; }
        .drop-zone svg { width: 48px; height: 48px; fill: #94a3b8; margin-bottom: 10px; }
        .drop-zone:hover svg, .drop-zone.dragover svg { fill: var(--primary-color); }
        
        .file-list { font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1rem; max-height: 100px; overflow-y: auto; }

        .options-panel {
            background-color: #f9fafb;
            padding: 1rem;
            border-radius: 8px;
            border: 1px solid var(--border-color);
            margin-bottom: 1.5rem;
            display: none; /* Dosya seçilene kadar gizli */
        }

        .option-group { margin-bottom: 1rem; }
        .option-group:last-child { margin-bottom: 0; }
        .option-group label { font-weight: 500; font-size: 0.9rem; display: block; margin-bottom: 0.5rem; }
        
        select { width: 100%; padding: 0.5rem; border: 1px solid var(--border-color); border-radius: 6px; font-family: inherit; }
        
        .radio-group { display: flex; gap: 1rem; }
        .radio-group label { font-weight: 400; display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer; }

        .warning-text { font-size: 0.8rem; color: #d97706; margin-top: 0.5rem; display: none; }

        .btn {
            background-color: var(--primary-color); color: white; border: none; padding: 0.875rem;
            width: 100%; border-radius: 8px; font-size: 1rem; font-weight: 500; cursor: pointer; display: none;
        }
        .btn:hover { background-color: var(--primary-hover); }
        .btn:disabled { background-color: #9ca3af; cursor: not-allowed; }

        .status-area { margin-top: 1.5rem; display: none; }
        .status-text { font-size: 0.875rem; font-weight: 500; margin-bottom: 0.5rem; display: flex; justify-content: space-between; }
        .progress-bar-bg { width: 100%; background-color: var(--border-color); border-radius: 999px; height: 8px; overflow: hidden; }
        .progress-bar-fill { height: 100%; background-color: var(--primary-color); width: 0%; transition: width 0.3s ease; }
    </style>
</head>
<body>

    <div class="card">
        <h2>PDF'den Resme</h2>
        <p class="subtitle">İstediğiniz formatta (PNG, JPG, WebP) dönüştürün ve indirin.</p>

        <div class="drop-zone" id="drop-zone">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
            <p><strong>Dosyaları buraya sürükleyin</strong></p>
            <p style="font-size: 0.8rem; color: #94a3b8;">veya seçmek için tıklayın</p>
            <input type="file" id="file-input" accept="application/pdf" multiple style="display: none;">
        </div>

        <div class="file-list" id="file-list"></div>

        <div class="options-panel" id="options-panel">
            <div class="option-group">
                <label>Görüntü Formatı:</label>
                <select id="image-format">
                    <option value="jpeg">JPEG (.jpg) - Küçük Boyut</option>
                    <option value="png" selected>PNG (.png) - Yüksek Kalite</option>
                    <option value="webp">WebP (.webp) - Modern Web Formatı</option>
                </select>
            </div>
            <div class="option-group">
                <label>İndirme Yöntemi:</label>
                <div class="radio-group">
                    <label><input type="radio" name="download-mode" value="zip" checked> Tek Bir ZIP Dosyası</label>
                    <label><input type="radio" name="download-mode" value="individual"> Ayrı Ayrı İndir</label>
                </div>
                <div class="warning-text" id="dl-warning">
                    ⚠️ Not: Çok fazla sayfa varsa, tarayıcınız "Çoklu dosya indirme" izni isteyebilir.
                </div>
            </div>
        </div>

        <button class="btn" id="convert-btn">Dönüştür ve İndir</button>

        <div class="status-area" id="status-area">
            <div class="status-text">
                <span id="status-message">Hazırlanıyor...</span>
                <span id="status-percentage">0%</span>
            </div>
            <div class="progress-bar-bg">
                <div class="progress-bar-fill" id="progress-bar"></div>
            </div>
        </div>
    </div>

    <script>
        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

        const dropZone = document.getElementById('drop-zone');
        const fileInput = document.getElementById('file-input');
        const fileList = document.getElementById('file-list');
        const optionsPanel = document.getElementById('options-panel');
        const convertBtn = document.getElementById('convert-btn');
        const statusArea = document.getElementById('status-area');
        const dlWarning = document.getElementById('dl-warning');
        
        let selectedFiles = [];

        // UI Olayları
        dropZone.addEventListener('click', () => fileInput.click());
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(evt => dropZone.addEventListener(evt, e => { e.preventDefault(); e.stopPropagation(); }));
        ['dragenter', 'dragover'].forEach(evt => dropZone.addEventListener(evt, () => dropZone.classList.add('dragover')));
        ['dragleave', 'drop'].forEach(evt => dropZone.addEventListener(evt, () => dropZone.classList.remove('dragover')));
        
        dropZone.addEventListener('drop', e => handleFiles(e.dataTransfer.files));
        fileInput.addEventListener('change', function() { handleFiles(this.files); });

        // İndirme yöntemi değiştiğinde uyarıyı göster/gizle
        document.querySelectorAll('input[name="download-mode"]').forEach(radio => {
            radio.addEventListener('change', (e) => {
                dlWarning.style.display = e.target.value === 'individual' ? 'block' : 'none';
            });
        });

        function handleFiles(files) {
            const newFiles = Array.from(files).filter(f => f.type === 'application/pdf');
            if(newFiles.length === 0) { alert("Lütfen PDF dosyası seçin."); return; }
            selectedFiles = newFiles;
            fileList.innerHTML = `<strong>Seçilen Dosyalar (${selectedFiles.length}):</strong><br>` + selectedFiles.map(f => `- ${f.name}`).join('<br>');
            optionsPanel.style.display = 'block';
            convertBtn.style.display = 'block';
            statusArea.style.display = 'none';
        }

        // Ana İşlem Döngüsü
        convertBtn.addEventListener('click', async () => {
            if (selectedFiles.length === 0) return;

            const format = document.getElementById('image-format').value;
            const mimeType = `image/${format}`;
            const isZipMode = document.querySelector('input[name="download-mode"]:checked').value === 'zip';
            const ext = format === 'jpeg' ? 'jpg' : format;

            convertBtn.disabled = true;
            convertBtn.innerText = "İşleniyor, Lütfen Bekleyin...";
            statusArea.style.display = 'block';
            
            let globalZip = isZipMode ? new JSZip() : null;
            let totalFiles = selectedFiles.length;

            try {
                for (let i = 0; i < totalFiles; i++) {
                    let file = selectedFiles[i];
                    let arrayBuffer = await file.arrayBuffer();
                    let pdf = await pdfjsLib.getDocument({data: arrayBuffer}).promise;
                    let totalPages = pdf.numPages;

                    for (let pageNum = 1; pageNum <= totalPages; pageNum++) {
                        let percent = Math.round(((pageNum - 1) / totalPages) * 100);
                        document.getElementById('status-message').innerText = `Dosya ${i+1}/${totalFiles} - Sayfa ${pageNum}/${totalPages}...`;
                        document.getElementById('status-percentage').innerText = `${percent}%`;
                        document.getElementById('progress-bar').style.width = `${percent}%`;

                        const page = await pdf.getPage(pageNum);
                        const viewport = page.getViewport({ scale: 2.0 });
                        const canvas = document.createElement('canvas');
                        const context = canvas.getContext('2d');
                        canvas.height = viewport.height;
                        canvas.width = viewport.width;

                        await page.render({ canvasContext: context, viewport: viewport }).promise;

                        // Canvas'ı resme dönüştür (JPEG için kalite 0.9 olarak ayarlandı)
                        const imgBlob = await new Promise(resolve => canvas.toBlob(resolve, mimeType, 0.9));
                        const fileName = `${file.name.replace('.pdf', '')}_S${pageNum}.${ext}`;

                        if (isZipMode) {
                            globalZip.file(fileName, imgBlob);
                        } else {
                            saveAs(imgBlob, fileName);
                            // Tarayıcının çoklu indirme engeline takılmamak için araya küçük bir gecikme ekliyoruz
                            await new Promise(r => setTimeout(r, 300));
                        }
                    }
                }

                if (isZipMode) {
                    document.getElementById('status-message').innerText = `Tüm dosyalar ZIP'leniyor...`;
                    document.getElementById('progress-bar').style.width = `100%`;
                    document.getElementById('status-percentage').innerText = `100%`;
                    
                    const content = await globalZip.generateAsync({type: "blob"});
                    saveAs(content, `PDF_Resimleri_Toplu.zip`);
                }

                document.getElementById('status-message').innerText = "İşlem Başarılı!";
                document.getElementById('progress-bar').style.backgroundColor = "#10b981";
                
            } catch (error) {
                console.error(error);
                document.getElementById('status-message').innerText = "Hata Oluştu!";
                document.getElementById('progress-bar').style.backgroundColor = "#ef4444";
            } finally {
                convertBtn.disabled = false;
                convertBtn.innerText = "Yeni Dosyaları Dönüştür";
            }
        });
    </script>
</body>
</html>
Hata oluştu yazıyor