Jak przeprowadzić migrację z CraftMyPDF do IronPDF w języku C#
Dlaczego warto przejść zCraftMyPDFna IronPDF?
Interfejsy API do obsługi plików PDF w chmurze, takie jak CraftMyPDF, wiążą się z podstawowymi problemami, które sprawiają, że nie nadają się one do wielu środowisk produkcyjnych.
Problem z interfejsami API do obsługi plików PDF w chmurze
-
Twoje dane opuszczają system: Każdy szablon HTML i ładunek danych JSON jest przesyłany na serwery CraftMyPDF. W przypadku faktur, umów, dokumentacji medycznej lub jakichkolwiek wrażliwych danych biznesowych stwarza to ryzyko związane z nieprzestrzeganiem przepisów HIPAA, RODO i SOC2.
-
Opóźnienie sieciowe: DokumentacjaCraftMyPDFpodaje, że przetwarzanie jednego pliku PDF zajmuje od 1,5 do 30 sekund.IronPDFgeneruje pliki lokalnie w ciągu milisekund.
-
Koszty związane z plikami PDF się sumują: 10 000 plików PDF miesięcznie w ramach abonamentu generuje znaczne koszty cykliczne w porównaniu z jednorazową Licencją wieczystą.
-
Wynik zoptymalizowany pod kątem PRINT: Interfejsy API w chmurze często są zoptymalizowane pod kątem PRINT — redukują tło i upraszczają kolory, aby oszczędzać "atrament". Wynik nigdy nie wygląda tak samo jak kod HTML na ekranie.
- Uzależnienie od szablonu:CraftMyPDFwymaga korzystania z własnego edytora typu "przeciągnij i upuść". Nie można swobodnie używać standardowego HTML/CSS.
Porównanie architektur
| Aspekt | CraftMyPDF | IronPDF |
|---|---|---|
| Lokalizacja danych | Chmura (Twoje dane opuszczają Twój system) | Lokalnie (dane nigdy nie opuszczają serwera) |
| Opóźnienie | 1,5–30 sekund na plik PDF | Milisekundy |
| Ceny | Subskrypcja na pliki PDF | Jednorazowa Licencja wieczysta |
| System szablonów | Wyłącznie zastrzeżone przeciąganie i upuszczanie | Dowolny kod HTML/CSS/JavaScript |
| Jakość tłumaczenia | Zoptymalizowane pod kątem druku | Renderowanie ekranu z dokładnością do piksela |
| Działa w trybie offline | Nie (wymagane połączenie z Internetem) | Tak |
| Zgodność | Dane opuszczają organizację | Zgodność z SOC2/HIPAA |
Porównanie funkcji
| Funkcja | CraftMyPDF | IronPDF |
|---|---|---|
| HTML do PDF | Za pośrednictwem szablonów API | ✅Język ojczysty |
| URL do pliku PDF | Poprzez API | ✅Język ojczysty |
| Szablony niestandardowe | Tylko w edytorze własnościowym | ✅Dowolny kod HTML |
| Obsługa CSS3 | Ograniczone | ✅Pełne |
| Renderowanie JavaScript | Ograniczone | ✅Pełne |
| Łączenie/dzielenie plików PDF | Poprzez API | ✅Język ojczysty |
| Znaki wodne | Poprzez API | ✅Język ojczysty |
| Działa w trybie offline | ❌ | ✅ |
| Własny hosting | ❌ | ✅ |
Przygotowania przed migracją
Wymagania wstępne
Upewnij się, że Twoje środowisko spełnia następujące wymagania:
- .NET Framework 4.6.2+ lub .NET Core 3.1 / .NET 5-9
- Visual Studio 2019+ lub VS Code z rozszerzeniem C#
- Dostęp do menedżera pakietów NuGet
- Klucz licencyjnyIronPDF(bezpłatna wersja próbna dostępna na stronie ironpdf.com)
Audyt wykorzystania CraftMyPDF
Uruchom te polecenia w katalogu rozwiązania, aby zidentyfikować wszystkie odwołania do CraftMyPDF:
# Find allCraftMyPDFusages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .
# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .
# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
# Find allCraftMyPDFusages in your codebase
grep -r "CraftMyPdf\|craftmypdf\|api.craftmypdf.com" --include="*.cs" .
grep -r "X-API-KEY" --include="*.cs" .
# Find API key references
grep -r "your-api-key\|template-id\|template_id" --include="*.cs" .
# Find NuGet package references
grep -r "CraftMyPdf\|RestSharp" --include="*.csproj" .
Zmiany wymagające dostosowania
| Zmiana | CraftMyPDF | IronPDF | Wpływ |
|---|---|---|---|
| Architektura | Cloud REST API | Lokalna biblioteka .NET | Usuń wywołania HTTP |
| Szablony | Własny edytor | Standardowy HTML | Konwersja szablonów do formatu HTML |
| Klucz API | Wymagane dla każdego wywołania | Licencja przy uruchomieniu | Usuń obsługę klucza API |
| Wzorzec asynchroniczny | Wymagane (HTTP) | Opcjonalnie | Usuń "await", jeśli wolisz |
| Obsługa błędów | Kody statusu HTTP | Wyjątki | Zmiana wzorców try/catch |
| Powiązanie danych | Szablony JSON | Interpolacja ciągów znaków | Uprość powiązanie danych |
Proces migracji krok po kroku
Krok 1: Zaktualizuj pakiety NuGet
Usuń bibliotekę klienta HTTP i zainstaluj IronPDF:
# Remove RestSharp HTTP client
dotnet remove package RestSharp
# Install IronPDF
dotnet add package IronPdf
# Remove RestSharp HTTP client
dotnet remove package RestSharp
# Install IronPDF
dotnet add package IronPdf
Krok 2: Aktualizacja odniesień do przestrzeni nazw
Zastąp przestrzenie nazw klienta HTTP przez IronPDF:
// Remove these
using RestSharp;
using System.IO;
// Add this
using IronPdf;
// Remove these
using RestSharp;
using System.IO;
// Add this
using IronPdf;
Imports IronPdf
Krok 3: Skonfiguruj licencję (jednorazowo podczas uruchamiania)
Zastąp nagłówki klucza API dla poszczególnych żądań pojedynczą konfiguracją licencji:
// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Global.asax)
// This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Global.asax)
' This replaces all X-API-KEY headers
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Kompletna dokumentacja API
Mapowanie punktów końcowych API
| CraftMyPDF | IronPDF |
|---|---|
POST /v1/create |
renderer.RenderHtmlAsPdf(html) |
X-API-KEY nagłówek |
License.LicenseKey = "..." |
template_id |
Standardowy ciąg znaków HTML |
{%name%} symbole zastępcze |
$"{name}" Interpolacja w języku C# |
POST /v1/merge |
PdfDocument.Merge(pdfs) |
POST /v1/add-watermark |
pdf.ApplyWatermark(html) |
| Wywołania zwrotne Webhook | Nie jest potrzebne |
| Ograniczanie szybkości | Nie dotyczy |
Mapowanie konfiguracji
| OpcjaCraftMyPDF | OdpowiednikIronPDF |
|---|---|
template_id |
Ciąg znaków HTML |
data JSON |
Interpolacja w języku C# |
page_size: "A4" |
PaperSize = PdfPaperSize.A4 |
orientation: "landscape" |
PaperOrientation = Landscape |
margin_top: 20 |
MarginTop = 20 |
header |
HtmlHeader |
footer |
HtmlFooter |
Przykłady migracji kodu
Konwersja HTML do PDF
Najczęstsza operacja ilustruje fundamentalną zmianę architektury z chmurowego API na renderowanie lokalne.
Wdrożenie CraftMyPDF:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("output.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("output.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.html = "<h1>Hello World</h1><p>This is a PDF from HTML</p>"
}
})
Dim response = client.Execute(request)
File.WriteAllBytes("output.pdf", response.RawBytes)
End Sub
End Module
Wdrożenie IronPDF:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>");
pdf.SaveAs("output.pdf");
}
}
Imports System
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML</p>")
pdf.SaveAs("output.pdf")
End Sub
End Class
IronPDF eliminuje konfigurację RestClient, nagłówki kluczy API, identyfikatory szablonów i obsługę odpowiedzi HTTP — redukując 15-wierszową operację w chmurze do 4 wierszy kodu lokalnego. Aby uzyskać więcej opcji, zapoznaj się z dokumentacją dotyczącą konwersji HTML do PDF.
Konwersja adresów URL do formatu PDF
Wdrożenie CraftMyPDF:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
url = "https://example.com"
},
export_type = "pdf"
});
var response = client.Execute(request);
File.WriteAllBytes("webpage.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
url = "https://example.com"
},
export_type = "pdf"
});
var response = client.Execute(request);
File.WriteAllBytes("webpage.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.url = "https://example.com"
},
.export_type = "pdf"
})
Dim response = client.Execute(request)
File.WriteAllBytes("webpage.pdf", response.RawBytes)
End Sub
End Module
Wdrożenie IronPDF:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports System
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
Metoda RenderUrlAsPdf firmyIronPDFprzechwytuje całą stronę internetową, w tym treści renderowane przez JavaScript. Aby uzyskać więcej opcji, zapoznaj się z dokumentacją dotyczącą konwersji URL na PDF.
Nagłówki i stopki
Wdrożenie CraftMyPDF:
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Document Content</h1>",
header = "<div>Page Header</div>",
footer = "<div>Page {page} of {total_pages}</div>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("document.pdf", response.RawBytes);
}
}
// NuGet: Install-Package RestSharp
using System;
using RestSharp;
using System.IO;
class Program
{
static void Main()
{
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
request.AddJsonBody(new
{
template_id = "your-template-id",
data = new
{
html = "<h1>Document Content</h1>",
header = "<div>Page Header</div>",
footer = "<div>Page {page} of {total_pages}</div>"
}
});
var response = client.Execute(request);
File.WriteAllBytes("document.pdf", response.RawBytes);
}
}
Imports System
Imports RestSharp
Imports System.IO
Module Program
Sub Main()
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
request.AddJsonBody(New With {
.template_id = "your-template-id",
.data = New With {
.html = "<h1>Document Content</h1>",
.header = "<div>Page Header</div>",
.footer = "<div>Page {page} of {total_pages}</div>"
}
})
Dim response = client.Execute(request)
File.WriteAllBytes("document.pdf", response.RawBytes)
End Sub
End Module
Wdrożenie IronPDF:
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}"
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header"
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}"
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("document.pdf");
}
}
Imports System
Imports IronPdf
Imports IronPdf.Rendering
Module Program
Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
.CenterText = "Page Header"
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
.CenterText = "Page {page} of {total-pages}"
}
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>")
pdf.SaveAs("document.pdf")
End Sub
End Module
IronPDF obsługuje tokeny zastępcze, takie jak {page} i {total-pages}, służące do dynamicznego numerowania stron. Aby uzyskać więcej opcji, zapoznaj się z dokumentacją dotyczącą nagłówków i stopek.
Konwersja zmiennych szablonu
CraftMyPDF wykorzystuje własne symbole zastępcze szablonów, które należy przekształcić na interpolację ciągów znaków w języku C#:
Wzór CraftMyPDF:
//CraftMyPDFtemplate variables
request.AddJsonBody(new
{
template_id = "invoice-template",
data = new
{
customer = "John Doe",
amount = "$1,000",
items = invoiceItems
}
});
//CraftMyPDFtemplate variables
request.AddJsonBody(new
{
template_id = "invoice-template",
data = new
{
customer = "John Doe",
amount = "$1,000",
items = invoiceItems
}
});
'CraftMyPDFtemplate variables
request.AddJsonBody(New With {
.template_id = "invoice-template",
.data = New With {
.customer = "John Doe",
.amount = "$1,000",
.items = invoiceItems
}
})
Wzór IronPDF:
// C# string interpolation
var html = $@"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
// C# string interpolation
var html = $@"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
Dim html As String = $"
<html>
<body>
<h1>Invoice</h1>
<p>Customer: {customerName}</p>
<p>Amount: {amount}</p>
{GenerateItemsTable(invoiceItems)}
</body>
</html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
Ważne uwagi dotyczące migracji
Usuń wszystkie kody HTTP
Najważniejszą zmianą jest wyeliminowanie zależności sieciowych.IronPDFdziała lokalnie — bez RestClient, bez wywołań API, bez obsługi odpowiedzi:
//CraftMyPDF- HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);
//IronPDF- no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
//CraftMyPDF- HTTP required
var client = new RestClient("https://api.craftmypdf.com/v1/create");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "your-api-key");
var response = await client.ExecuteAsync(request);
//IronPDF- no HTTP
var pdf = renderer.RenderHtmlAsPdf(html);
Imports RestSharp
'CraftMyPDF- HTTP required
Dim client As New RestClient("https://api.craftmypdf.com/v1/create")
Dim request As New RestRequest(Method.POST)
request.AddHeader("X-API-KEY", "your-api-key")
Dim response = Await client.ExecuteAsync(request)
'IronPDF- no HTTP
Dim pdf = renderer.RenderHtmlAsPdf(html)
Usuń kod ograniczający szybkość
CraftMyPDF nakłada ograniczenia szybkości API, co wymaga logiki ponownych prób.IronPDFnie ma ograniczeń:
//CraftMyPDF- needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }
//IronPDF- no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
//CraftMyPDF- needed to avoid 429 errors
await Task.Delay(100);
if (response.StatusCode == TooManyRequests) { /* retry */ }
//IronPDF- no limits, just generate
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all rate limit code!
Usuń procedury obsługi webhooków
CraftMyPDF wykorzystuje asynchroniczne webhooki do tworzenia plików PDF.IronPDFdziała synchronicznie — plik PDF jest gotowy natychmiast:
//CraftMyPDF- webhook callback required
// POST with webhook_url, wait for callback
//IronPDF- PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
//CraftMyPDF- webhook callback required
// POST with webhook_url, wait for callback
//IronPDF- PDF ready immediately
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No callback needed!
'CraftMyPDF- webhook callback required
' POST with webhook_url, wait for callback
'IronPDF- PDF ready immediately
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' No callback needed!
Synchronizacja domyślna
Usuń wzorce async/await, jeśli były one potrzebne wyłącznie do wywołań HTTP:
//CraftMyPDF- async required
var response = await client.ExecuteAsync(request);
//IronPDF- sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
//CraftMyPDF- async required
var response = await client.ExecuteAsync(request);
//IronPDF- sync by default (async available if needed)
var pdf = renderer.RenderHtmlAsPdf(html);
Lista kontrolna po migracji
Po zakończeniu migracji kodu sprawdź, czy:
- Uruchom wszystkie testy generowania plików PDF
- Porównaj jakość wyjściową (silnik Chromium wIronPDFzapewnia renderowanie z idealną dokładnością pikselową)
- Mierzenie poprawy wydajności (w milisekundach vs. sekundach)
- Sprawdź, czy wszystkie szablony zostały poprawnie przekonwertowane
- Testowanie przetwarzania wsadowego bez limitów szybkości
- Przetestuj we wszystkich środowiskach docelowych
- Aktualizacja potoków CI/CD
- Anuluj subskrypcję CraftMyPDF
- Usuń klucz API z pliku secrets/config
Zabezpieczenie infrastruktury PDF na przyszłość
W obliczu zbliżającej się premiery .NET 10 i wprowadzenia nowych funkcji językowych w C# 14, wybór lokalnej biblioteki PDF eliminuje ryzyko wycofania API w chmurze oraz obawy dotyczące kompatybilności wersji. Model licencji wieczystejIronPDFoznacza, że inwestycja w migrację przynosi korzyści w nieskończoność, ponieważ projekty rozciągają się na lata 2025 i 2026 — bez powtarzających się kosztów subskrypcji i bez wyprowadzania danych poza infrastrukturę.
Dodatkowe zasoby
- Dokumentacja IronPDF
- Samouczki dotyczące konwersji HTML do PDF
- Dokumentacja API
- Pakiet NuGet
- Opcje licencyjne
Przejście zCraftMyPDFnaIronPDFeliminuje zależność od chmury, opóźnienia sieciowe, koszty związane z każdym plikiem PDF oraz uzależnienie od szablonów, zapewniając jednocześnie idealne renderowanie w Chromium, które działa w trybie offline. Przejście z wywołań REST API na lokalne wywołania metod upraszcza kod źródłowy i pozwala zachować poufne dane dokumentów w ramach własnej infrastruktury.

