/
kantser
/
sait
Обзор
Документация
Войти
/
kantser
/
sait
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/lib/cloudinary.ts
155 строк
4 KB
Edward
Добавил облочное хранение фото в сервис Cloudinary
13 окт 2025, 20:18
13 окт 2025, 20:18
48b4bec
Код
Авторство
О чём код?
// Cloudinary configuration and utilities import { v2 as cloudinary } from 'cloudinary'; // Конфигурация Cloudinary (серверная сторона) cloudinary.config({ cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET, secure: true }); export { cloudinary }; /** * Типы изображений для организации в папки */ export type ImageType = 'dogs' | 'puppies' | 'images' | 'team' | 'hero'; /** * Параметры загрузки изображения в Cloudinary */ export interface CloudinaryUploadOptions { folder?: string; transformation?: any[]; format?: 'auto' | 'jpg' | 'png' | 'webp'; quality?: 'auto' | number; width?: number; height?: number; crop?: 'fill' | 'fit' | 'scale' | 'limit'; } /** * Результат загрузки в Cloudinary */ export interface CloudinaryUploadResult { success: boolean; url?: string; publicId?: string; secureUrl?: string; width?: number; height?: number; format?: string; bytes?: number; error?: string; } /** * Загрузка изображения в Cloudinary (серверная функция) */ export async function uploadToCloudinary( fileBuffer: Buffer, type: ImageType, options: CloudinaryUploadOptions = {} ): Promise<CloudinaryUploadResult> { try { const defaultOptions = { folder: `kennel/${type}`, resource_type: 'image' as const, quality: 'auto:good', transformation: [ { width: 1920, height: 1080, crop: 'limit' }, { quality: 'auto:good' } ] }; const uploadOptions = { ...defaultOptions, ...options }; return new Promise((resolve, reject) => { const uploadStream = cloudinary.uploader.upload_stream( uploadOptions, (error, result) => { if (error) { console.error('Cloudinary upload error:', error); resolve({ success: false, error: error.message }); } else if (result) { resolve({ success: true, url: result.url, publicId: result.public_id, secureUrl: result.secure_url, width: result.width, height: result.height, format: result.format, bytes: result.bytes }); } } ); uploadStream.end(fileBuffer); }); } catch (error: any) { console.error('Cloudinary upload error:', error); return { success: false, error: error.message }; } } /** * Удаление изображения из Cloudinary */ export async function deleteFromCloudinary(publicId: string): Promise<boolean> { try { const result = await cloudinary.uploader.destroy(publicId); return result.result === 'ok'; } catch (error) { console.error('Cloudinary delete error:', error); return false; } } /** * Получение оптимизированного URL изображения */ export function getCloudinaryUrl( publicId: string, options: { width?: number; height?: number; crop?: 'fill' | 'fit' | 'scale'; quality?: 'auto' | number | string; format?: 'jpg' | 'png' | 'webp'; } = {} ): string { const urlOptions: any = { ...options, secure: true, quality: options.quality || 'auto' }; // Добавляем format только если указан if (options.format) { urlOptions.format = options.format; } return cloudinary.url(publicId, urlOptions); } /** * Получение трансформированного URL для разных размеров */ export function getResponsiveUrls(publicId: string) { return { thumbnail: getCloudinaryUrl(publicId, { width: 150, height: 150, crop: 'fill' }), small: getCloudinaryUrl(publicId, { width: 400, height: 300, crop: 'fill' }), medium: getCloudinaryUrl(publicId, { width: 800, height: 600, crop: 'fill' }), large: getCloudinaryUrl(publicId, { width: 1200, height: 900, crop: 'fill' }), full: getCloudinaryUrl(publicId, { quality: 'auto:best' }) }; }