PixAI-Tagger-v0.9-ONNX / fetch_url_util.py
DraconicDragon's picture
Update fetch_url_util.py
18120fc verified
Raw
History Blame
3.6 kB
import io
import os
import hashlib
import urllib.parse
from PIL import Image
from curl_cffi import requests
try:
import pillow_jxl
except ImportError:
pass
CACHE_DIR = "/tmp/image_fetch_cache"
MAX_CACHE_COUNT = 100
MAX_SIZE = 150 * 1024 * 1024
MAX_SIZE_MB = MAX_SIZE / (1024 * 1024)
# Ensure cache directory exists
os.makedirs(CACHE_DIR, exist_ok=True)
def _manage_cache_limit():
"""Removes the oldest files if cache exceeds MAX_CACHE_COUNT."""
files = [os.path.join(CACHE_DIR, f) for f in os.listdir(CACHE_DIR)]
if len(files) > MAX_CACHE_COUNT:
# Sort by access time (oldest first)
files.sort(key=os.path.getatime)
for i in range(len(files) - MAX_CACHE_COUNT):
try:
os.remove(files[i])
except OSError:
pass
def fetch_image_from_url(url):
if not url:
return None
url = url.strip()
if not url.startswith(("http://", "https://")):
url = "https://" + url
# Generate a unique filename based on the URL
url_hash = hashlib.sha256(url.encode()).hexdigest()
cache_path = os.path.join(CACHE_DIR, f"{url_hash}.png")
# 1. Check if image is in cache
if os.path.exists(cache_path):
try:
img = Image.open(cache_path)
img.load()
# Update access time so it's not cleared by cache manager
os.utime(cache_path, None)
return img.convert("RGB")
except Exception:
# If cached file is corrupt, remove it and proceed to fetch
os.remove(cache_path)
# 2. If not in cache, prepare to fetch
parsed_url = urllib.parse.urlparse(url)
base_domain = f"{parsed_url.scheme}://{parsed_url.netloc}/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.7559.59 Safari/537.36",
"Accept": "image/avif,image/webp,image/jxl,image/apng,image/png,image/jpeg,image/gif,image/svg+xml,image/*,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Referer": base_domain,
"Cache-Control": "no-cache",
}
response = None
try:
response = requests.get(
url,
headers=headers,
impersonate="chrome120",
timeout=15,
allow_redirects=True,
stream=True
)
response.raise_for_status()
cl = response.headers.get("Content-Length")
if cl and int(cl) > MAX_SIZE:
raise RuntimeError(f"File too large (limit: {MAX_SIZE_MB:.0f}MB)")
downloaded_data = io.BytesIO()
size = 0
for chunk in response.iter_content(chunk_size=65536):
size += len(chunk)
if size > MAX_SIZE:
raise RuntimeError(f"File exceeds {MAX_SIZE_MB:.0f}MB limit.")
downloaded_data.write(chunk)
downloaded_data.seek(0)
img = Image.open(downloaded_data)
img.load()
# 3. Save to cache
try:
img.save(cache_path, "PNG")
_manage_cache_limit()
except Exception as cache_err:
print(f"Cache write failed: {cache_err}")
return img.convert("RGB")
except Exception as e:
error_msg = f"Fetch Error: {str(e)}"
print(error_msg)
try:
import gradio as gr
raise gr.Error(error_msg)
except ImportError:
raise RuntimeError(error_msg)
finally:
if response is not None:
response.close()