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 @@
+