DKNet is an enterprise-grade .NET library collection focused on advanced EF Core extensions, dynamic predicate building, and the Specification pattern. It provides production-ready tools for building robust, type-safe, and testable data access layers, including dynamic LINQ support, LinqKit integration. Designed for modern cloud-native applications, DKNet enforces strict code quality, async best practices, and full documentation for all public APIs. Enterprise-grade .NET library suite for modern application development, featuring advanced EF Core extensions (dynamic predicates, specifications, LinqKit), robust Domain-Driven Design (DDD) patterns, and domain event support. DKNet empowers scalable, maintainable, and testable solutions with type-safe validation, async/await, XML documentation, and high code quality standards. Ideal for cloud-native, microservices, and enterprise architectures.
$ dotnet add package DKNet.Svc.BlobStorage.AbstractionsCore abstractions and interfaces for blob storage services, providing a unified API for file storage operations across different providers (Azure Blob Storage, AWS S3, Local File System). This package defines contracts for storage operations, data models, and configuration options.
Install via NuGet Package Manager:
dotnet add package DKNet.Svc.BlobStorage.Abstractions
Or via Package Manager Console:
Install-Package DKNet.Svc.BlobStorage.Abstractions
using DKNet.Svc.BlobStorage.Abstractions;
public class DocumentService
{
private readonly IBlobService _blobService;
public DocumentService(IBlobService blobService)
{
_blobService = blobService;
}
public async Task<string> UploadDocumentAsync(string fileName, byte[] content, string contentType)
{
var blob = new BlobData
{
Name = $"documents/{fileName}",
Content = content,
ContentType = contentType
};
return await _blobService.SaveAsync(blob);
}
public async Task<byte[]?> DownloadDocumentAsync(string fileName)
{
var request = new BlobRequest($"documents/{fileName}");
var result = await _blobService.GetAsync(request);
return result?.Content;
}
}
public async Task<string> UploadLargeFileAsync(string fileName, Stream fileStream, string contentType)
{
var blob = new BlobData
{
Name = $"uploads/{fileName}",
ContentStream = fileStream,
ContentType = contentType
};
return await _blobService.SaveAsync(blob);
}
public async Task<Stream?> DownloadAsStreamAsync(string fileName)
{
var request = new BlobRequest($"uploads/{fileName}");
var result = await _blobService.GetAsync(request);
return result?.ContentStream;
}
using Microsoft.Extensions.DependencyInjection;
using DKNet.Svc.BlobStorage.Abstractions;
// Register your chosen implementation
services.Configure<BlobServiceOptions>(options =>
{
options.ContainerName = "my-container";
options.EnableMetadata = true;
options.MaxFileSize = 100 * 1024 * 1024; // 100MB
});
// IBlobService implementation will be provided by specific provider package
// e.g., DKNet.Svc.BlobStorage.AzureStorage, DKNet.Svc.BlobStorage.AwsS3
public class BlobServiceOptions
{
public string ContainerName { get; set; } = "default";
public bool EnableMetadata { get; set; } = true;
public long MaxFileSize { get; set; } = 50 * 1024 * 1024; // 50MB default
public string[] AllowedExtensions { get; set; } = Array.Empty<string>();
public string[] BlockedExtensions { get; set; } = { ".exe", ".bat", ".cmd" };
public bool GenerateUniqueNames { get; set; } = false;
public string PathPrefix { get; set; } = string.Empty;
}
IBlobService - Main blob storage operations interfaceSaveAsync(BlobData, CancellationToken) - Save blob data and return locationGetAsync(BlobRequest, CancellationToken) - Retrieve blob with contentGetItemAsync(BlobRequest, CancellationToken) - Retrieve blob metadata onlyListItemsAsync(BlobRequest, CancellationToken) - List blobs with optional filteringDeleteAsync(BlobRequest, CancellationToken) - Delete blobExistsAsync(BlobRequest, CancellationToken) - Check if blob existsBlobData - Blob content with metadata for upload operationsBlobRequest - Request parameters for blob operationsBlobResult - Blob metadata without contentBlobDataResult - Blob metadata with contentBlobDetails - Detailed blob information (size, type, timestamps)BlobTypes - Enumeration for File/Directory typesSaveTextAsync(string, string) - Save text content directlyGetTextAsync(string) - Retrieve content as textSaveJsonAsync<T>(string, T) - Save object as JSONGetJsonAsync<T>(string) - Retrieve and deserialize JSONpublic async Task<BlobDetails?> GetFileInfoAsync(string fileName)
{
var request = new BlobRequest(fileName);
var result = await _blobService.GetItemAsync(request);
return result?.Details;
}
public async Task ListDocumentsAsync()
{
var request = new BlobRequest("documents/")
{
Type = BlobTypes.Directory
};
await foreach (var blob in _blobService.ListItemsAsync(request))
{
Console.WriteLine($"File: {blob.Name}");
if (blob.Details != null)
{
Console.WriteLine($" Size: {blob.Details.ContentLength} bytes");
Console.WriteLine($" Type: {blob.Details.ContentType}");
Console.WriteLine($" Modified: {blob.Details.LastModified}");
}
}
}
public class ImageService
{
private readonly IBlobService _blobService;
private readonly IImageProcessor _imageProcessor;
public ImageService(IBlobService blobService, IImageProcessor imageProcessor)
{
_blobService = blobService;
_imageProcessor = imageProcessor;
}
public async Task<string> UploadImageWithThumbnailAsync(string fileName, byte[] imageData)
{
// Upload original image
var originalBlob = new BlobData
{
Name = $"images/original/{fileName}",
Content = imageData,
ContentType = "image/jpeg"
};
var originalLocation = await _blobService.SaveAsync(originalBlob);
// Create and upload thumbnail
var thumbnailData = await _imageProcessor.CreateThumbnailAsync(imageData, 150, 150);
var thumbnailBlob = new BlobData
{
Name = $"images/thumbnails/{fileName}",
Content = thumbnailData,
ContentType = "image/jpeg"
};
await _blobService.SaveAsync(thumbnailBlob);
return originalLocation;
}
}
public async Task<List<string>> UploadMultipleFilesAsync(IEnumerable<(string name, byte[] content, string contentType)> files)
{
var uploadTasks = files.Select(async file =>
{
var blob = new BlobData
{
Name = file.name,
Content = file.content,
ContentType = file.contentType
};
return await _blobService.SaveAsync(blob);
});
return (await Task.WhenAll(uploadTasks)).ToList();
}
public async Task DeleteMultipleFilesAsync(IEnumerable<string> fileNames)
{
var deleteTasks = fileNames.Select(async fileName =>
{
var request = new BlobRequest(fileName);
await _blobService.DeleteAsync(request);
});
await Task.WhenAll(deleteTasks);
}
[ApiController]
[Route("api/[controller]")]
public class FilesController : ControllerBase
{
private readonly IBlobService _blobService;
public FilesController(IBlobService blobService)
{
_blobService = blobService;
}
[HttpPost("upload")]
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded");
using var stream = file.OpenReadStream();
var blob = new BlobData
{
Name = $"uploads/{Guid.NewGuid()}/{file.FileName}",
ContentStream = stream,
ContentType = file.ContentType
};
var location = await _blobService.SaveAsync(blob);
return Ok(new { Location = location });
}
[HttpGet("download/{fileName}")]
public async Task<IActionResult> DownloadFile(string fileName)
{
var request = new BlobRequest($"uploads/{fileName}");
var result = await _blobService.GetAsync(request);
if (result == null)
return NotFound();
return File(result.Content, result.ContentType ?? "application/octet-stream", fileName);
}
}
public async Task<string?> SafeUploadAsync(string fileName, byte[] content, string contentType)
{
try
{
var blob = new BlobData
{
Name = fileName,
Content = content,
ContentType = contentType
};
return await _blobService.SaveAsync(blob);
}
catch (ArgumentException ex)
{
// Handle invalid file name or content
_logger.LogError(ex, "Invalid file data for {FileName}", fileName);
return null;
}
catch (InvalidOperationException ex)
{
// Handle storage service errors
_logger.LogError(ex, "Storage service error for {FileName}", fileName);
return null;
}
catch (Exception ex)
{
// Handle unexpected errors
_logger.LogError(ex, "Unexpected error uploading {FileName}", fileName);
throw;
}
}
See the main CONTRIBUTING.md for guidelines on how to contribute to this project.
This project is licensed under the MIT License.
Part of the DKNet Framework - A comprehensive .NET framework for building modern, scalable applications.