import { existsSync, createWriteStream, mkdirSync } from "fs"; import { dirname } from "path"; import axios from "axios"; import { Logger } from "@nestjs/common"; export class ImageUtils { private static readonly logger = new Logger("ImageUtils"); /** * Downloads an image from a URL and saves it to a local path. * Skips download if file already exists. */ static async downloadImage(url: string, localPath: string): Promise { try { // Check if file exists if (existsSync(localPath)) { return true; } // Ensure directory exists const dir = dirname(localPath); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } // Download const response = await axios({ url, method: "GET", responseType: "stream", timeout: 5000, validateStatus: (status) => status === 200, // Only save if 200 OK }); const writer = createWriteStream(localPath); response.data.pipe(writer); return new Promise((resolve, reject) => { writer.on("finish", () => resolve(true)); writer.on("error", (err) => { this.logger.warn( `Failed to write image to ${localPath}: ${err.message}`, ); reject(new Error(`Failed to write image to ${localPath}`)); }); }); } catch (error: any) { // Log warning but don't break the application // 404s are common for missing logos if (error.response?.status !== 404) { this.logger.warn( `Failed to download image from ${url}: ${error.message}`, ); } return false; } } }