1515
1616class StorageService :
1717 """
18- Handles local file storage for generated images .
18+ Handles image storage — local filesystem and Open WebUI file upload .
1919 """
2020
2121 def __init__ (self ):
@@ -24,15 +24,35 @@ def __init__(self):
2424
2525 async def save_image (self , image_data : bytes , extension : str = "png" ) -> str :
2626 """
27- Save image bytes to local storage.
27+ Save image bytes to the best available storage.
28+
29+ When OPENWEBUI_MODE is enabled and OWUI upload is configured, uploads
30+ to Open WebUI's file storage and returns an OWUI file URL. Falls back
31+ to local storage on failure or when OWUI upload is not configured.
2832
2933 Args:
3034 image_data: Raw image bytes
3135 extension: File extension (png, jpg, webp)
3236
3337 Returns:
34- Public URL to access the image
38+ Public URL to access the image (OWUI URL or local URL)
3539 """
40+ # Try OWUI upload when in OWUI mode with upload configured
41+ if settings .OPENWEBUI_MODE and settings .openwebui_upload_available :
42+ try :
43+ owui_url = await self ._upload_to_openwebui (image_data , extension )
44+ # Also save locally if configured
45+ if settings .SAVE_IMAGES_LOCALLY :
46+ await self ._save_locally (image_data , extension )
47+ return owui_url
48+ except Exception as e :
49+ logger .warning (f"OWUI upload failed, falling back to local storage: { e } " )
50+
51+ # Local storage
52+ return await self ._save_locally (image_data , extension )
53+
54+ async def _save_locally (self , image_data : bytes , extension : str = "png" ) -> str :
55+ """Save image bytes to local filesystem."""
3656 filename = f"{ uuid .uuid4 ()} .{ extension } "
3757 filepath = self .storage_path / filename
3858
@@ -41,6 +61,28 @@ async def save_image(self, image_data: bytes, extension: str = "png") -> str:
4161
4262 return f"{ settings .IMAGE_BASE_URL .rstrip ('/' )} /images/{ filename } "
4363
64+ async def _upload_to_openwebui (self , image_data : bytes , extension : str = "png" ) -> str :
65+ """
66+ Upload image to Open WebUI's file storage.
67+
68+ Returns:
69+ OWUI file URL (e.g. http://open-webui:3000/api/v1/files/{id}/content)
70+ """
71+ filename = f"{ uuid .uuid4 ()} .{ extension } "
72+ mime_type = f"image/{ extension } "
73+ base_url = settings .OPENWEBUI_BASE_URL .rstrip ("/" )
74+
75+ async with httpx .AsyncClient (timeout = 30.0 ) as client :
76+ response = await client .post (
77+ f"{ base_url } /api/v1/files/" ,
78+ files = {"file" : (filename , image_data , mime_type )},
79+ headers = {"Authorization" : f"Bearer { settings .OPENWEBUI_API_KEY } " },
80+ )
81+ response .raise_for_status ()
82+ file_id = response .json ()["id" ]
83+ logger .info (f"Uploaded image to OWUI: { file_id } " )
84+ return f"{ base_url } /api/v1/files/{ file_id } /content"
85+
4486 async def get_image (self , url : str ) -> bytes :
4587 """
4688 Retrieve image bytes from URL or local storage.
0 commit comments