![]() |
VOOZH | about |
dotnet add package Pervaxis.Genesis.FileStorage.AWS --version 3.4.4
NuGet\Install-Package Pervaxis.Genesis.FileStorage.AWS -Version 3.4.4
<PackageReference Include="Pervaxis.Genesis.FileStorage.AWS" Version="3.4.4" />
<PackageVersion Include="Pervaxis.Genesis.FileStorage.AWS" Version="3.4.4" />Directory.Packages.props
<PackageReference Include="Pervaxis.Genesis.FileStorage.AWS" />Project file
paket add Pervaxis.Genesis.FileStorage.AWS --version 3.4.4
#r "nuget: Pervaxis.Genesis.FileStorage.AWS, 3.4.4"
#:package Pervaxis.Genesis.FileStorage.AWS@3.4.4
#addin nuget:?package=Pervaxis.Genesis.FileStorage.AWS&version=3.4.4Install as a Cake Addin
#tool nuget:?package=Pervaxis.Genesis.FileStorage.AWS&version=3.4.4Install as a Cake Tool
AWS S3 file storage provider for the Pervaxis Genesis platform — scalable object storage with presigned URLs, multipart uploads, and metadata management.
Pervaxis.Genesis.FileStorage.AWS implements the IFileStorage abstraction from Pervaxis.Core.Abstractions using the AWS SDK for S3. It provides:
<PackageReference Include="Pervaxis.Genesis.FileStorage.AWS" Version="1.0.0" />
{
"FileStorage": {
"Region": "ap-south-1",
"BucketName": "my-app-files",
"KeyPrefix": "uploads/",
"DefaultPresignedUrlExpiryMinutes": 60,
"MultipartUploadThresholdBytes": 5242880,
"MultipartUploadPartSizeBytes": 5242880,
"StorageClass": "INTELLIGENT_TIERING",
"EnableServerSideEncryption": true,
"KmsKeyId": "arn:aws:kms:ap-south-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}
}
| Property | Type | Default | Description |
|---|---|---|---|
Region |
string |
(required) | AWS region (e.g., "ap-south-1", "us-east-1") |
BucketName |
string |
(required) | S3 bucket name |
KeyPrefix |
string |
"" |
Optional prefix for all keys (e.g., "uploads/", "tenant-123/") |
DefaultPresignedUrlExpiryMinutes |
int |
60 |
Default presigned URL expiration in minutes |
MultipartUploadThresholdBytes |
long |
5242880 (5MB) |
File size threshold for multipart upload |
MultipartUploadPartSizeBytes |
long |
5242880 (5MB) |
Part size for multipart uploads (5MB-5GB) |
StorageClass |
string |
"STANDARD" |
S3 storage class (STANDARD, INTELLIGENT_TIERING, GLACIER, etc.) |
EnableServerSideEncryption |
bool |
true |
Enable server-side encryption |
KmsKeyId |
string? |
null |
KMS key ID for encryption (optional, uses AES256 if not set) |
UseLocalEmulator |
bool |
false |
Enable LocalStack support |
LocalEmulatorUrl |
Uri? |
null |
LocalStack URL (defaults to http://localhost:4566) |
For local development with LocalStack:
{
"FileStorage": {
"Region": "us-east-1",
"BucketName": "test-bucket",
"UseLocalEmulator": true,
"LocalEmulatorUrl": "http://localhost:4566"
}
}
using Pervaxis.Genesis.FileStorage.AWS.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Register S3 file storage
builder.Services.AddGenesisFileStorage(
builder.Configuration.GetSection("FileStorage"));
using Pervaxis.Genesis.FileStorage.AWS.Extensions;
using Pervaxis.Genesis.FileStorage.AWS.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGenesisFileStorage(options =>
{
options.Region = "ap-south-1";
options.BucketName = "my-app-files";
options.KeyPrefix = "uploads/";
options.EnableServerSideEncryption = true;
});
using Pervaxis.Core.Abstractions.Genesis.Modules;
public class DocumentService
{
private readonly IFileStorage _fileStorage;
public DocumentService(IFileStorage fileStorage)
{
_fileStorage = fileStorage;
}
public async Task<string> UploadDocumentAsync(Stream content, string fileName)
{
// Upload file (returns full S3 key)
var key = await _fileStorage.UploadAsync(
key: $"documents/{fileName}",
content: content,
contentType: "application/pdf");
return key;
}
public async Task<Stream?> DownloadDocumentAsync(string key)
{
// Download file (returns null if not found)
return await _fileStorage.DownloadAsync(key);
}
public async Task<bool> DeleteDocumentAsync(string key)
{
// Delete file
return await _fileStorage.DeleteAsync(key);
}
public async Task<bool> CheckDocumentExistsAsync(string key)
{
// Check if file exists
return await _fileStorage.ExistsAsync(key);
}
}
public class FileShareService
{
private readonly IFileStorage _fileStorage;
public FileShareService(IFileStorage fileStorage)
{
_fileStorage = fileStorage;
}
public async Task<string> GenerateDownloadLinkAsync(string key)
{
// Generate presigned URL valid for 1 hour
var url = await _fileStorage.GetPresignedUrlAsync(
key: key,
expiry: TimeSpan.FromHours(1));
return url;
}
public async Task<string> GenerateTemporaryShareLinkAsync(string key)
{
// Generate presigned URL valid for 15 minutes
var url = await _fileStorage.GetPresignedUrlAsync(
key: key,
expiry: TimeSpan.FromMinutes(15));
return url;
}
}
public async Task<string> UploadWithMetadataAsync(
Stream content,
string fileName,
string uploadedBy)
{
var metadata = new Dictionary<string, string>
{
["uploaded-by"] = uploadedBy,
["uploaded-at"] = DateTime.UtcNow.ToString("O"),
["file-type"] = "document"
};
var key = await _fileStorage.UploadAsync(
key: $"documents/{fileName}",
content: content,
contentType: "application/pdf",
metadata: metadata);
return key;
}
public async Task<IDictionary<string, string>> GetFileMetadataAsync(string key)
{
// Retrieve metadata
return await _fileStorage.GetMetadataAsync(key);
}
public async Task<IEnumerable<string>> ListUserDocumentsAsync(string userId)
{
// List all files with prefix
var files = await _fileStorage.ListAsync(
prefix: $"users/{userId}/documents/");
return files;
}
public async Task<IEnumerable<string>> ListAllFilesAsync()
{
// List all files in bucket (respecting KeyPrefix from config)
return await _fileStorage.ListAsync();
}
The provider automatically uses multipart upload for files larger than MultipartUploadThresholdBytes:
public async Task<string> UploadLargeFileAsync(Stream largeFile, string fileName)
{
// Automatically uses multipart upload if file > threshold (default 5MB)
var key = await _fileStorage.UploadAsync(
key: $"large-files/{fileName}",
content: largeFile,
contentType: "video/mp4");
return key;
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetObjectMetadata"
],
"Resource": [
"arn:aws:s3:::my-app-files/*",
"arn:aws:s3:::my-app-files"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetObjectMetadata"
],
"Resource": [
"arn:aws:s3:::my-app-files/*",
"arn:aws:s3:::my-app-files"
]
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:Encrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:ap-south-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}
]
}
All operations throw GenesisException on failure:
using Pervaxis.Genesis.Base.Exceptions;
try
{
await _fileStorage.UploadAsync(key, content);
}
catch (GenesisException ex)
{
_logger.LogError(ex, "File upload failed: {Message}", ex.Message);
// Handle error (e.g., return error response)
}
docker run -d -p 4566:4566 localstack/localstack
aws --endpoint-url=http://localhost:4566 s3 mb s3://test-bucket
{
"FileStorage": {
"Region": "us-east-1",
"BucketName": "test-bucket",
"UseLocalEmulator": true,
"LocalEmulatorUrl": "http://localhost:4566"
}
}
Cause: Insufficient IAM permissions or bucket policy restrictions.
Solution:
Cause: S3 bucket name is incorrect or doesn't exist.
Solution:
BucketName in configuration matches actual bucket nameCause: Part size too small or network interruption.
Solution:
MultipartUploadPartSizeBytes is at least 5MB"MultipartUploadPartSizeBytes": 10485760 (10MB)Cause: URL expired or bucket/object permissions incorrect.
Solution:
DefaultPresignedUrlExpiryMinutes)Cause: KeyPrefix configuration not applied correctly.
Solution:
KeyPrefix in options (e.g., "uploads/")/ for proper path constructionEnableServerSideEncryption: true)tenant-{id}/)UploadAsync callsLicense: Proprietary — Clarivex Technologies Private Limited
Product: Pervaxis Platform
Website: https://clarivex.tech
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.