From f32972b55fa88fa5cd44e7aa3a7dcc5376839fac Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 1 Oct 2026 01:16:24 +0330 Subject: [PATCH] adding File Content Extraction Services ... --- Interfaces/IXFileContentExtractor.cs | 26 ++++++++ Providers/XCompositeFileContentExtractor.cs | 68 ++++++++++++++++++++ Providers/XPdfContentExtractor.cs | 69 +++++++++++++++++++++ Providers/XPlainTextContentExtractor.cs | 54 ++++++++++++++++ Startup.cs | 6 ++ xAiApi.csproj | 4 +- 6 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 Interfaces/IXFileContentExtractor.cs create mode 100644 Providers/XCompositeFileContentExtractor.cs create mode 100644 Providers/XPdfContentExtractor.cs create mode 100644 Providers/XPlainTextContentExtractor.cs diff --git a/Interfaces/IXFileContentExtractor.cs b/Interfaces/IXFileContentExtractor.cs new file mode 100644 index 0000000..7349d11 --- /dev/null +++ b/Interfaces/IXFileContentExtractor.cs @@ -0,0 +1,26 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace xAiApi.Interfaces +{ + /// + /// a Service for Extracting File Content ... + /// + public interface IXFileContentExtractor + { + /// + /// Check if this extractor supports the specified MIME type ... + /// + bool CanExtract(string mimeType); + + /// + /// Extract text content from file stream ... + /// + Task ExtractAsync( + Stream fileStream, + string mimeType, + CancellationToken cancellationToken = default + ); + } +} \ No newline at end of file diff --git a/Providers/XCompositeFileContentExtractor.cs b/Providers/XCompositeFileContentExtractor.cs new file mode 100644 index 0000000..4dc747f --- /dev/null +++ b/Providers/XCompositeFileContentExtractor.cs @@ -0,0 +1,68 @@ +using System.IO; +using System.Linq; +using System.Threading; +using xAiApi.Interfaces; +using xCommons.Extensions; +using xExceptions.Constants; +using System.Threading.Tasks; +using System.Collections.Generic; + +namespace xAiApi.Providers +{ + /// + /// Composite extractor that delegates to appropriate extractor + /// based on MIME type ... + /// + public class XCompositeFileContentExtractor : IXFileContentExtractor + { + // + private readonly IEnumerable extractors; + + public XCompositeFileContentExtractor( + IEnumerable extractors + ) + { + this.extractors = extractors; + } + + /// + /// Check if this extractor supports the specified MIME type ... + /// + public bool CanExtract(string mimeType) + { + return extractors.Any(e => e.CanExtract(mimeType)); + } + + /// + /// Extract text content from file stream ... + /// + public async Task ExtractAsync( + Stream fileStream, + string mimeType, + CancellationToken cancellationToken = default + ) + { + // + var extractor = extractors + .FirstOrDefault(e => e.CanExtract(mimeType)); + if (extractor.IsNull()) + { + // + XException.NotAllowed.Throw( + $"Unsupported file type: {mimeType}" + ); + } + + // + var result = await extractor + .ExtractAsync( + mimeType: mimeType, + fileStream: fileStream, + cancellationToken: cancellationToken + ); + + // + return result; + } + } +} \ No newline at end of file diff --git a/Providers/XPdfContentExtractor.cs b/Providers/XPdfContentExtractor.cs new file mode 100644 index 0000000..22afa57 --- /dev/null +++ b/Providers/XPdfContentExtractor.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using UglyToad.PdfPig; +using System.Threading; +using xAiApi.Interfaces; +using System.Threading.Tasks; + +namespace xAiApi.Providers +{ + /// + /// Extracts content from PDF files using PdfPig ... + /// + public class XPdfContentExtractor : IXFileContentExtractor + { + /// + /// Supported MIME Types ... + /// + private static readonly string[] SupportedMimeTypes = + [ + "application/pdf" + ]; + + /// + /// Check if this extractor supports the specified MIME type ... + /// + public bool CanExtract(string mimeType) + { + // + return SupportedMimeTypes.Contains( + mimeType?.ToLowerInvariant() ?? string.Empty + ); + } + + /// + /// Extract text content from file stream ... + /// + public async Task ExtractAsync( + Stream fileStream, + string mimeType, + CancellationToken cancellationToken = default + ) + { + // + var result = await Task.Run(() => + { + // + var sb = new StringBuilder(); + using var document = PdfDocument.Open(fileStream); + foreach (var page in document.GetPages()) + { + // + var text = page.Text; + + // + sb.AppendLine(text); + sb.AppendLine(); + } + + // + return sb.ToString(); + }, cancellationToken); + + // + return result; + } + } +} \ No newline at end of file diff --git a/Providers/XPlainTextContentExtractor.cs b/Providers/XPlainTextContentExtractor.cs new file mode 100644 index 0000000..d704221 --- /dev/null +++ b/Providers/XPlainTextContentExtractor.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading; +using xAiApi.Interfaces; +using System.Threading.Tasks; + +namespace xAiApi.Providers +{ + /// + /// Extracts content from plain text files (txt, md, csv, json, xml) ... + /// + public class XPlainTextContentExtractor : IXFileContentExtractor + { + /// + /// Supported MIME Types ... + /// + private static readonly string[] SupportedMimeTypes = + [ + "text/plain", + "text/markdown", + "text/csv", + "text/html", + "text/xml", + "application/json", + "application/xml" + ]; + + /// + /// Check if this extractor supports the specified MIME type ... + /// + public bool CanExtract(string mimeType) + { + // + return SupportedMimeTypes.Contains( + mimeType?.ToLowerInvariant() ?? string.Empty + ); + } + + /// + /// Extract text content from file stream ... + /// + public async Task ExtractAsync( + Stream fileStream, + string mimeType, + CancellationToken cancellationToken = default + ) + { + // + using var reader = new StreamReader(fileStream); + return await reader.ReadToEndAsync(); + } + } +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index 21ea129..5674408 100644 --- a/Startup.cs +++ b/Startup.cs @@ -185,6 +185,12 @@ namespace xAiApi // Register XAiApi Configuration ... services.AddXAiApiConfiguration(Configuration); + // + // Register File Content Extractors ... + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + // // Register Default Ai Service ... services.AddScoped(); diff --git a/xAiApi.csproj b/xAiApi.csproj index a7e3641..cd82fb1 100644 --- a/xAiApi.csproj +++ b/xAiApi.csproj @@ -24,8 +24,7 @@ - + @@ -48,6 +47,7 @@ +