Spaces:
Build error
Build error
""" | |
Utility module for generating file viewer HTML content. | |
""" | |
import base64 | |
import mimetypes | |
import os | |
def generate_file_viewer_html(file_path: str) -> str: | |
""" | |
Generate HTML content for viewing different file types. | |
Args: | |
file_path: The absolute path to the file | |
Returns: | |
str: HTML content for viewing the file | |
Raises: | |
ValueError: If the file extension is not supported | |
""" | |
file_extension = os.path.splitext(file_path)[1].lower() | |
file_name = os.path.basename(file_path) | |
# Define supported file extensions | |
supported_extensions = [ | |
'.pdf', | |
'.png', | |
'.jpg', | |
'.jpeg', | |
'.gif', | |
] | |
# Check if the file extension is supported | |
if file_extension not in supported_extensions: | |
raise ValueError( | |
f'Unsupported file extension: {file_extension}. ' | |
f'Supported extensions are: {", ".join(supported_extensions)}' | |
) | |
# Check if the file exists | |
if not os.path.exists(file_path): | |
raise ValueError( | |
f'File not found locally: {file_path}. Please download the file to the local machine and try again.' | |
) | |
# Read file content directly | |
file_content = None | |
mime_type = mimetypes.guess_type(file_path)[0] or 'application/octet-stream' | |
# For binary files (images, PDFs), encode as base64 | |
if file_extension in ['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp']: | |
with open(file_path, 'rb') as file: | |
file_content = base64.b64encode(file.read()).decode('utf-8') | |
# For text files, read as text | |
else: | |
with open(file_path, 'r', encoding='utf-8') as file: | |
file_content = file.read() | |
return f"""<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>File Viewer - {file_name}</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script> | |
<style> | |
body, html {{ margin: 0; padding: 0; height: 100%; overflow: hidden; font-family: Arial, sans-serif; }} | |
#viewer-container {{ width: 100%; height: 100vh; overflow: auto; }} | |
.page {{ margin: 10px auto; box-shadow: 0 0 10px rgba(0,0,0,0.3); }} | |
.text-content {{ margin: 20px; white-space: pre-wrap; font-family: monospace; line-height: 1.5; }} | |
.error {{ color: red; margin: 20px; }} | |
img {{ max-width: 100%; margin: 20px auto; display: block; }} | |
</style> | |
</head> | |
<body> | |
<div id="viewer-container"></div> | |
<script> | |
const filePath = "{file_path}"; | |
const fileExtension = "{file_extension}"; | |
const fileContent = `{file_content if file_extension not in ['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp'] else ''}`; | |
const fileBase64 = "{file_content if file_extension in ['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp'] else ''}"; | |
const mimeType = "{mime_type}"; | |
const container = document.getElementById('viewer-container'); | |
async function loadContent() {{ | |
try {{ | |
if (fileExtension === '.pdf') {{ | |
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; | |
const binaryString = atob(fileBase64); | |
const bytes = new Uint8Array(binaryString.length); | |
for (let i = 0; i < binaryString.length; i++) {{ | |
bytes[i] = binaryString.charCodeAt(i); | |
}} | |
const loadingTask = pdfjsLib.getDocument({{data: bytes.buffer}}); | |
const pdf = await loadingTask.promise; | |
// Get total number of pages | |
const numPages = pdf.numPages; | |
// Render each page | |
for (let pageNum = 1; pageNum <= numPages; pageNum++) {{ | |
const page = await pdf.getPage(pageNum); | |
// Set scale for rendering | |
const viewport = page.getViewport({{ scale: 1.5 }}); | |
// Create canvas for rendering | |
const canvas = document.createElement('canvas'); | |
canvas.className = 'page'; | |
canvas.width = viewport.width; | |
canvas.height = viewport.height; | |
container.appendChild(canvas); | |
// Render PDF page into canvas context | |
const context = canvas.getContext('2d'); | |
const renderContext = {{ | |
canvasContext: context, | |
viewport: viewport | |
}}; | |
await page.render(renderContext).promise; | |
}} | |
}} else if (['.png', '.jpg', '.jpeg', '.gif', '.bmp'].includes(fileExtension)) {{ | |
const img = document.createElement('img'); | |
img.src = `data:${{mimeType}};base64,${{fileBase64}}`; | |
img.alt = filePath.split('/').pop(); | |
container.appendChild(img); | |
}} else {{ | |
const pre = document.createElement('pre'); | |
pre.className = 'text-content'; | |
pre.textContent = fileContent; | |
container.appendChild(pre); | |
}} | |
}} catch (error) {{ | |
console.error('Error:', error); | |
container.innerHTML = `<div class="error"><h2>Error loading file</h2><p>${{error.message}}</p></div>`; | |
}} | |
}} | |
window.onload = loadContent; | |
</script> | |
</body> | |
</html>""" | |