Kod Gösterimi
C# WebSocketMiddleware.cs
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Threading;


namespace ImageEffectApp.Web.Services
{

    public class WebSocketMiddleware
    {
        private readonly RequestDelegate _next;
        private static readonly ConcurrentDictionary _sockets = new();

        public WebSocketMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path == "/ws")
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    var webSocket = await context.WebSockets.AcceptWebSocketAsync();
                    var socketId = Guid.NewGuid();
                    _sockets.TryAdd(socketId, webSocket);

                    Console.WriteLine($"Yeni WebSocket bağlantısı: {socketId}");

                    await ReceiveMessages(webSocket);

                    _sockets.TryRemove(socketId, out _);
                }
                else
                {
                    context.Response.StatusCode = 400;
                }
            }
            else
            {
                await _next(context);
            }
        }

        private async Task ReceiveMessages(WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];

            while (webSocket.State == WebSocketState.Open)
            {
                var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);

                if (result.MessageType == WebSocketMessageType.Text)
                {
                    string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    Console.WriteLine($"WebSocket mesajı alındı: {message}");


                    await SendMessageToClients(message);
                }
                else if (result.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
                }
            }
        }

        public static async Task SendMessageToClients(string message)
        {
            var buffer = Encoding.UTF8.GetBytes(message);
            var tasks = _sockets.Values
                .Where(s => s.State == WebSocketState.Open)
                .Select(s => s.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None));

            await Task.WhenAll(tasks);
        }
    }


}






C# RabbitMQPublisher.cs
using ImageEffectApp.Web.Models;
using ImageEffectApp.WorkerService.Models;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using System.Net.Security;
using System.Text;
using System.Text.Json;

namespace ImageEffectApp.Web.Services
{
    public class RabbitMQPublisher
    {
        private readonly string _hostName;
        private readonly string _queueName;


        public RabbitMQPublisher(IOptions options)
        {
            _hostName = options.Value.HostName;
            _queueName= options.Value.QueueName;

        }


        public async Task PublishMessage(ImageProcessingRequest message)
        {
            try
            {
                var factory = new ConnectionFactory()
                {
                    Uri = new Uri(_hostName),
                    Ssl = new SslOption
                    {
                        Enabled = true,
                        AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors |
                         SslPolicyErrors.RemoteCertificateNameMismatch |
                         SslPolicyErrors.RemoteCertificateNotAvailable
                    }
                };
                await using var connection = await factory.CreateConnectionAsync();
                await using var channel = await connection.CreateChannelAsync();
                await channel.QueueDeclareAsync(_queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
                var jsonMessage = JsonSerializer.Serialize(message);
                var body = Encoding.UTF8.GetBytes(jsonMessage);
                await channel.BasicPublishAsync(
                    exchange: "",
                    routingKey: _queueName,
                    mandatory: false,
                    basicProperties: new BasicProperties(),
                    body: body
                );
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.ToString());
            }
        }
    }
}
C# ClearController.cs
using Microsoft.AspNetCore.Mvc;

namespace ImageEffectApp.Web.Controllers
{
    [ApiController]
    [Route("api/delete")]
    public class ClearController : ControllerBase
    {


        private readonly string _uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads");
        private readonly string _processedFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "processed");

        [HttpDelete]
        public IActionResult Clear()
        {
            try
            {
                if (Directory.Exists(_uploadsFolder))
                {
                    var files = Directory.GetFiles(_uploadsFolder);
                    var deletedFiles = new List();

                    foreach (var file in files)
                    {
                        try
                        {
                            var creationTime = System.IO.File.GetCreationTime(file);
                            if (creationTime < DateTime.Now.AddMinutes(-5))
                            {
                                System.IO.File.Delete(file);
                                deletedFiles.Add(file);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Error deleting file {file}: {ex.Message}");
                        }
                    }


                }
                else
                {
                    return NotFound("Uploads folder not found.");
                }
                if (Directory.Exists(_processedFolder))
                {
                    var files = Directory.GetFiles(_processedFolder);
                    var deletedFiles = new List();

                    foreach (var file in files)
                    {
                        try
                        {
                            var creationTime = System.IO.File.GetCreationTime(file);
                            if (creationTime < DateTime.Now.AddMinutes(-5))
                            {
                                System.IO.File.Delete(file);
                                deletedFiles.Add(file);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Error deleting file {file}: {ex.Message}");
                        }
                    }


                }
                else
                {
                    return NotFound("Processed folder not found.");
                }
                return Ok();
            }
            catch (Exception ex)
            { 
                Console.WriteLine($"Error: {ex.Message}");
                return StatusCode(500, "Internal server error.");
            }
        }



    }
}






C# ImageProcessor.cs
using ImageEffectApp.WorkerService.Models;
using Microsoft.Extensions.Options;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System.Net.Http.Headers;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;

namespace ImageEffectApp.WorkerService.Processing
{
    public class ImageProcessor : IImageProcessor
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly string _uploadUrl;
        private readonly string _webSocketUrl;
        public ImageProcessor(IHttpClientFactory httpClientFactory, IOptions options)
        {
            _httpClientFactory = httpClientFactory;
            _uploadUrl = options.Value.UploadUrl;
            _webSocketUrl = options.Value.WebSocketUrl;
        }

        public async Task ProcessImageAsync(ImageProcessingRequest request, CancellationToken cancellationToken)
        {
            try
            {
                if (request is null)
                {
                    throw new ArgumentNullException(nameof(request), "İstek nesnesi null olamaz!");
                }
                if (string.IsNullOrWhiteSpace(request.ImagePath) || string.IsNullOrWhiteSpace(request.OutputName))
                {
                    throw new ArgumentException("Resim yolu veya çıktı adı boş olamaz!");
                }

                string localImagePath;

                if (request.ImagePath.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    localImagePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");

                    using (var httpClient = _httpClientFactory.CreateClient())
                    using (var response = await httpClient.GetAsync(request.ImagePath, cancellationToken))
                    {
                        if (!response.IsSuccessStatusCode)
                        {
                            throw new HttpRequestException($"Resim indirme başarısız! HTTP {response.StatusCode}");
                        }

                        await using var fs = new FileStream(localImagePath, FileMode.Create, FileAccess.Write, FileShare.None);
                        await response.Content.CopyToAsync(fs);
                    }
                }
                else
                {
                    localImagePath = request.ImagePath;
                }

                string fileName = string.IsNullOrWhiteSpace(request.OutputName) ? $"{Guid.NewGuid()}.png" : request.OutputName;
                string tempOutputPath = Path.Combine(Path.GetTempPath(), fileName);

                using (var image = await Image.LoadAsync(localImagePath, cancellationToken))
                {
                    image.Mutate(x => x.Grayscale());
                    await image.SaveAsync(tempOutputPath, cancellationToken);
                }

                await UploadImageToServer(tempOutputPath, cancellationToken);

                try
                {
                    if (File.Exists(localImagePath)) File.Delete(localImagePath);
                    if (File.Exists(tempOutputPath)) File.Delete(tempOutputPath);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"❌ Dosya silme hatası: {ex.Message}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ Hata: {ex}");
                throw;
            }
        }


        public async Task UploadImageToServer(string filePath, CancellationToken cancellationToken)
        {



            try
            {
                if (!File.Exists(filePath))
                {
                    Console.WriteLine($"Dosya bulunamadı: {filePath}");
                    return false;
                }

                using (var httpClient = _httpClientFactory.CreateClient())
                using (var form = new MultipartFormDataContent())
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    var fileContent = new StreamContent(fileStream);
                    fileContent.Headers.ContentType = new MediaTypeHeaderValue(GetMimeType(filePath));
                    form.Add(fileContent, "file", Path.GetFileName(filePath));

                    Console.WriteLine($"Resim yükleniyor: {filePath} -> {_uploadUrl}");
                    var response = await httpClient.PostAsync(_uploadUrl, form, cancellationToken);

                    await SendWebSocketNotification(Path.GetFileName(filePath));

                    return true;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Hata oluştu: {ex.Message}");
                return false;
            }
        }

        private async Task SendWebSocketNotification(string fileName)
        {
            try
            {

                using (var webSocket = new ClientWebSocket())
                {

                    Uri serverUri = new Uri(_webSocketUrl);
                    await webSocket.ConnectAsync(serverUri, CancellationToken.None);


                    var notification = new
                    {
                        type = "image_processed",
                        imageId = fileName.Substring(0, fileName.LastIndexOf('.')),
                        outputPath = $"/processed/{fileName}",
                        timestamp = DateTime.UtcNow.ToString("o"),
                        success = true
                    };


                    string jsonMessage = JsonSerializer.Serialize(notification);
                    byte[] messageBytes = Encoding.UTF8.GetBytes(jsonMessage);


                    await webSocket.SendAsync(
                        new ArraySegment(messageBytes),
                        WebSocketMessageType.Text,
                        true,
                        CancellationToken.None
                    );

                    await webSocket.CloseAsync(
                        WebSocketCloseStatus.NormalClosure,
                        "Notification sent",
                        CancellationToken.None
                    );

                    Console.WriteLine($"WebSocket bildirimi gönderildi: Image ID {fileName}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"WebSocket bildirimi gönderilemedi: {ex.Message}");
            }
        }



        private string GetMimeType(string filePath)
        {
            string extension = Path.GetExtension(filePath).ToLowerInvariant();
            return extension switch
            {
                ".jpg" or ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".tiff" => "image/tiff",
                _ => "application/octet-stream"
            };
        }
    }
}



                
;