Spaces:
Running
Running
| <html> | |
| <head> | |
| <title>Protected File Download</title> | |
| <style> | |
| .hidden { | |
| display: none; | |
| } | |
| .container { | |
| max-width: 600px; | |
| margin: 50px auto; | |
| padding: 20px; | |
| font-family: Arial, sans-serif; | |
| } | |
| .error { | |
| color: red; | |
| margin-top: 10px; | |
| } | |
| .success { | |
| color: green; | |
| margin-top: 10px; | |
| } | |
| button, input, select { | |
| margin: 10px 0; | |
| padding: 8px; | |
| width: 100%; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div id="passwordSection"> | |
| <h2>Enter Password</h2> | |
| <input type="password" id="password" placeholder="Enter password"> | |
| <button onclick="checkPassword()">Submit</button> | |
| <div id="passwordError" class="error hidden"></div> | |
| </div> | |
| <div id="itemSection" class="hidden"> | |
| <h2>Select Item</h2> | |
| <select id="itemSelect"> | |
| <option value="">Choose an item...</option> | |
| </select> | |
| <button id="downloadButton" class="hidden" onclick="downloadItem()">Download</button> | |
| </div> | |
| </div> | |
| <script> | |
| // Add event listener for Enter key | |
| document.getElementById('password').addEventListener('keypress', function(event) { | |
| if (event.key === 'Enter') { | |
| event.preventDefault(); | |
| checkPassword(); | |
| } | |
| }); | |
| async function checkPassword() { | |
| const password = document.getElementById('password').value; | |
| // sleep for 2 seconds | |
| await new Promise(resolve => setTimeout(resolve, 2000)); | |
| try { | |
| const response = await fetch('/api/verify-password', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ password: password }) | |
| }); | |
| if (response.ok) { | |
| const items = await response.json(); | |
| showItemSection(items); | |
| } else { | |
| document.getElementById('passwordError').textContent = 'Invalid password'; | |
| document.getElementById('passwordError').classList.remove('hidden'); | |
| } | |
| } catch (error) { | |
| console.error('Error:', error); | |
| document.getElementById('passwordError').textContent = 'Error connecting to server'; | |
| document.getElementById('passwordError').classList.remove('hidden'); | |
| } | |
| } | |
| function showItemSection(items) { | |
| document.getElementById('passwordSection').classList.add('hidden'); | |
| document.getElementById('itemSection').classList.remove('hidden'); | |
| const select = document.getElementById('itemSelect'); | |
| items.forEach(item => { | |
| const option = document.createElement('option'); | |
| option.value = item; | |
| option.textContent = item; | |
| select.appendChild(option); | |
| }); | |
| select.addEventListener('change', function() { | |
| const downloadButton = document.getElementById('downloadButton'); | |
| downloadButton.classList.toggle('hidden', !this.value); | |
| }); | |
| } | |
| async function downloadItem() { | |
| const item = document.getElementById('itemSelect').value; | |
| try { | |
| const response = await fetch(`/api/download/${item}`); | |
| if (!response.ok) throw new Error('Download failed'); | |
| const blob = await response.blob(); | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = item; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| window.URL.revokeObjectURL(url); | |
| } catch (error) { | |
| console.error('Error:', error); | |
| alert('Error downloading file'); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |