Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/filo-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ jobs:
--api-key "${{ secrets.NUGET_KEY }}" `
--skip-duplicate
# ── Publish to GitHub Packages ─────────────────────────────────
# GITHUB_TOKEN is automatically available + has package:write permission
dotnet nuget push "$nupkg" `
--source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" `
--api-key "${{ secrets.GITHUB_TOKEN }}" `
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/filo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Ytdlp.NET

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:

runs-on: windows-latest

steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Restore dependencies
run: dotnet restore src/Filo/Filo.csproj
- name: Build
run: dotnet build src/Filo/Filo.csproj -c Release
132 changes: 83 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,35 @@
![NuGet Downloads](https://img.shields.io/nuget/dt/Filo)
![Visitors](https://visitor-badge.laobi.icu/badge?page_id=manusoft/FiloContainer)

---

<img width="512" height="512" alt="FILO" src="https://github.com/user-attachments/assets/d26100b0-2d96-480c-80b1-3e6501ebcd33" />

## FILO v1.1 Highlights

**Added:**

* ✔ Chunk integrity hashing (SHA256)
* ✔ Password-based encryption (PBKDF2)

**Deprecated:**

* ⚠ `WithEncryption(byte[] key)` — use `WithPassword(string password)` instead.

---

## Overview

**FILO** (Files In, Layered & Organized) is a modern **multi-file container format** for .NET designed to handle **large files efficiently**.
**FILO** (Files In, Layered & Organized) is a modern **multi-file container format** for .NET designed for **large files**.
It stores multiple files (video, audio, text, binaries, etc.) in a **single container**, supporting:

- **Large files** (videos, audio, binaries)
- **Multiple files per container**
- Chunked streaming for **GB-sized files**
- AES256 optional encryption per chunk
- Metadata storage
- File checksums for integrity
- Fully async and memory-efficient operations
* **Large files** (GB-sized videos, audio, binaries)
* **Multiple files per container**
* **Chunked streaming** for memory-efficient reads
* **AES256 optional encryption per chunk**
* **Embedded metadata**
* **File checksums** for integrity
* Fully **async APIs**

> FILO = **Files In, Layered & Organized**

It is ideal for **video/audio streaming, backup containers, and custom file packaging**.
> FILO = **Files In, Layered & Organized** — ideal for **video/audio streaming, backups, and custom file packaging**.

---

Expand Down Expand Up @@ -106,7 +114,7 @@ Traditional ZIP or JSON-based storage has limitations:
Install via NuGet:

```bash
dotnet add package Filo.1.0.0
dotnet add package Filo --version 1.1.0
````

---
Expand All @@ -117,15 +125,14 @@ dotnet add package Filo.1.0.0

```csharp
using Filo;
using System.Security.Cryptography;

var key = RandomNumberGenerator.GetBytes(32); // AES256 key
var pwd = "mypassword";

var writer = new FiloWriter("backup.filo")
.AddFile("video.mp4", new FileMetadata { MimeType = "video/mp4" })
.AddFile("subtitle.srt", new FileMetadata { MimeType = "text/plain" })
.WithChunkSize(5_000_000)
.WithEncryption(key);
.WithPassword(pwd);

await writer.WriteAsync();
Console.WriteLine("FILO container created!");
Expand All @@ -137,73 +144,90 @@ Console.WriteLine("FILO container created!");
var reader = new FiloReader("backup.filo");
await reader.InitializeAsync();

// List files in container
var key = reader.DeriveKey("mypassword");

// List files
foreach (var file in reader.ListFiles())
Console.WriteLine(file);

// Stream a file (AES256 encrypted example)
// Stream chunks
await foreach (var chunk in reader.StreamFileAsync("video.mp4", key))
{
// Process chunk
await chunk.WriteAsync(chunk);
}
```

---

## Streaming Video/Audio
### Direct Streaming

FILO supports **direct streaming without reassembling the file**:
```csharp
using var stream = reader.OpenStream("video.mp4", key);
await stream.CopyToAsync(outputFile);
```

### Extract Files Using `FiloStream`

```csharp
await using var filoStream = new FiloStream(reader, "video.mp4", key);
await using var output = new FileStream("video_streamed.mp4", FileMode.Create);
using var filoStream = new FiloStream(reader, "video.mp4", key);
using var output = File.Create("video_restored.mp4");

await filoStream.CopyToAsync(output);
Console.WriteLine("File extracted!");
```

### Load Image

```csharp
using var stream = new FiloStream(reader, "photo.jpg");
using var image = System.Drawing.Image.FromStream(stream);

Console.WriteLine($"Loaded image: {image.Width}x{image.Height}");

```

### In Blazor Server / ASP.NET Core
## Streaming Video/Audio in ASP.NET Core / Blazor

```csharp
[HttpGet("video/{fileName}")]
public async Task<IActionResult> StreamVideo(string fileName)
public async Task<IActionResult> GetVideo()
{
var reader = new FiloReader("backup.filo");
var reader = new FiloReader("media.filo");
await reader.InitializeAsync();
var filoStream = new FiloStream(reader, fileName, key: YourKeyHere);

return File(filoStream, "video/mp4", enableRangeProcessing: true);
var key = reader.DeriveKey("password");
var stream = new FiloStream(reader, "movie.mp4", key);

return File(stream, "video/mp4");
}
```

* Supports **large files**, **streaming**, and **AES256 encrypted chunks**
* Browser can **seek**, **pause**, and **resume** seamlessly
> Supports **large files**, **streaming**, and **AES256 encrypted chunks**. Browser can **seek, pause, and resume** seamlessly.

---

## Multi-file container

You can store multiple files in the same container:
## Multi-file Container Example

```csharp
var writer = new FiloWriter("media.filo")
.AddFile("movie.mp4", new FileMetadata { MimeType = "video/mp4" })
.AddFile("audio.mp3", new FileMetadata { MimeType = "audio/mpeg" })
.AddFile("subtitle.srt", new FileMetadata { MimeType = "text/plain" })
.WithChunkSize(10_000_000)
.WithEncryption(key);
.WithPassword("mypassword");

await writer.WriteAsync();
```

* The container will store **indexes, metadata, and checksums**.
* You can **stream each file individually** using `FiloStream` or `StreamFileAsync`.
* Stores **indexes, metadata, and checksums**
* Stream **each file individually** using `FiloStream` or `StreamFileAsync`

---

## Chunked Streaming

* FILO reads files in **chunks** to minimize memory usage.
* Suitable for **large video/audio files**.
* Supports **AES256 encryption per chunk**.
* Reads files in **memory-efficient chunks**
* Ideal for **large video/audio files**
* Supports **AES256 encryption per chunk**

```csharp
await foreach (var chunk in reader.StreamFileAsync("largevideo.mp4", key))
Expand All @@ -212,31 +236,41 @@ await foreach (var chunk in reader.StreamFileAsync("largevideo.mp4", key))
}
```

> Always verify checksum for **large file integrity**.
---

## ⚡ When to Use FiloStream vs StreamFileAsync

| Method | Best For |
| ------------------| ---------------- |
| StreamFileAsync() | chunk processing |
| FiloStream normal | file streaming |
| CopyToAsync() | extraction |
| HTTP streaming | media servers |

---

## Checksums & Integrity
> Always verify checksum for **large file integrity**.


FILO stores **SHA256 checksums** for each file:
## Checksums & Integrity

```csharp
var checksum = await FiloChecksum.ComputeFileSHA256Async("video.mp4");
Console.WriteLine(checksum);
```

You can verify that **streamed files match the original**.
* Ensures **streamed files match the original**

---

## Fluent API Summary

| Class | Key Methods |
| ------------------ | ---------------------------------------------------------------------- |
| `FiloWriter` | `.AddFile()`, `.WithChunkSize()`, `.WithEncryption()`, `.WriteAsync()` |
| `FiloReader` | `.InitializeAsync()`, `.ListFiles()`, `.StreamFileAsync()` |
| `FiloStream` | `.ReadAsync()` – supports streaming directly to players |
| `FiloChecksum` | `.ComputeFileSHA256Async()`, `.ComputeFileSHA256Async()`, `.ComputeSHA256()`, `.Verify()`,`.VerifyFileAsync()` |
| `FiloWriter` | `.AddFile()`, `AddDirectory()`, `.WithChunkSize()`, `.WithPassword()`, `.WriteAsync()` |
| `FiloReader` | `.InitializeAsync()`, `DeriveKey()`, `FileExists()`, `GetFileInfo()`, `.ListFiles()`, `.StreamFileAsync()`, `OpenStream()`, `ExtractFileAsync()`, `ExtractDirectoryAsync()`, `ReadHeaderAsync()` |
| `FiloStream` | `.ReadAsync()` – supports streaming directly to players, `Read()` |
| `FiloChecksum` | `.ComputeSHA256()`, `.ComputeSHA256Async()`, `.ComputeFileSHA256Async()`, `.ComputeFileSHA256Async()`,`.Verify()`, `VerifyFileAsync()` |
| `FiloEncryption` | `.Encrypt()`, `.Decrypt()` |

---
Expand Down
Loading
Loading