1+ import os
2+ import mimetypes
3+ from flask import Response , send_file
4+ from ai4birds_ingest_service import config , logger
5+
6+ class HeatmapFilesService :
7+ """Service for handling heatmap files operations."""
8+
9+ def __init__ (self ):
10+ # Directorio donde se almacenan las imágenes de mapas de calor
11+ self .heatmaps_directory = '/app/ai4birds_ingest_service/heatmaps'
12+ logger .info (f"Initialized HeatmapFilesService with directory: { self .heatmaps_directory } " )
13+ logger .info (f"Directory exists: { os .path .exists (self .heatmaps_directory )} " )
14+ logger .info (f"Is directory: { os .path .isdir (self .heatmaps_directory )} " )
15+ if os .path .exists (self .heatmaps_directory ):
16+ logger .info (f"Contents: { os .listdir (self .heatmaps_directory )} " )
17+
18+ def get_heatmap_file_response (self , filename : str ):
19+ """Get heatmap file as HTTP response for direct file serving.
20+
21+ Args:
22+ filename (str): Name of the heatmap file
23+
24+ Returns:
25+ Flask Response: File response or error response
26+ """
27+ logger .info (f"Requesting heatmap file response: { filename } " )
28+
29+ try :
30+ # Validar que el archivo existe
31+ if not self ._file_exists (filename ):
32+ logger .warning (f"Heatmap file not found: { filename } " )
33+ return Response ("File not found" , status = 404 )
34+
35+ # Validar que es una imagen válida
36+ if not self ._is_valid_image_file (filename ):
37+ logger .warning (f"Invalid file type requested: { filename } " )
38+ return Response ("Invalid file type. Only image files are allowed" , status = 400 )
39+
40+ # Servir el archivo directamente
41+ file_path = os .path .join (self .heatmaps_directory , filename )
42+
43+ # Obtener el tipo MIME
44+ mime_type , _ = mimetypes .guess_type (filename )
45+ if not mime_type :
46+ mime_type = 'application/octet-stream'
47+
48+ logger .info (f"Serving heatmap file response: { filename } " )
49+ return send_file (
50+ file_path ,
51+ mimetype = mime_type ,
52+ as_attachment = False ,
53+ download_name = filename
54+ )
55+
56+ except Exception as e :
57+ logger .error (f"Error serving heatmap file response { filename } : { e } " )
58+ return Response (f"Internal server error: { str (e )} " , status = 500 )
59+
60+ def _file_exists (self , filename : str ) -> bool :
61+ """Check if file exists in heatmaps directory.
62+
63+ Args:
64+ filename (str): Name of the file to check
65+
66+ Returns:
67+ bool: True if file exists, False otherwise
68+ """
69+ file_path = os .path .join (self .heatmaps_directory , filename )
70+ return os .path .isfile (file_path )
71+
72+ def _is_valid_image_file (self , filename : str ) -> bool :
73+ """Check if file has a valid image extension.
74+
75+ Args:
76+ filename (str): Name of the file to check
77+
78+ Returns:
79+ bool: True if file has valid image extension, False otherwise
80+ """
81+ valid_extensions = {'.png' , '.jpg' , '.jpeg' , '.gif' , '.bmp' , '.webp' , '.svg' }
82+ file_extension = os .path .splitext (filename .lower ())[1 ]
83+ return file_extension in valid_extensions
84+
85+ def list_heatmap_files (self ):
86+ """List all available heatmap files.
87+
88+ Returns:
89+ tuple: List of files and status code
90+ """
91+ logger .info ("Listing all heatmap files" )
92+
93+ try :
94+ if not os .path .exists (self .heatmaps_directory ):
95+ logger .warning ("Heatmaps directory does not exist" )
96+ return {"files" : [], "message" : "Heatmaps directory not found" }, 404
97+
98+ files = []
99+ for filename in os .listdir (self .heatmaps_directory ):
100+ file_path = os .path .join (self .heatmaps_directory , filename )
101+ if os .path .isfile (file_path ) and self ._is_valid_image_file (filename ):
102+ files .append ({
103+ "filename" : filename ,
104+ "size" : os .path .getsize (file_path ),
105+ "modified" : os .path .getmtime (file_path )
106+ })
107+
108+ logger .info (f"Found { len (files )} heatmap files" )
109+ return {"files" : files , "count" : len (files )}, 200
110+
111+ except Exception as e :
112+ logger .error (f"Error listing heatmap files: { e } " )
113+ return {"error" : f"Failed to list files: { str (e )} " }, 500
0 commit comments