OpenHands / openhands /runtime /utils /file_viewer.py
Backup-bdg's picture
Upload 964 files
51ff9e5 verified
Raw
History Blame Contribute Delete
5.56 kB
"""
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>"""