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
10 changes: 10 additions & 0 deletions DotNET/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copy to ".env" and set your values.

# Required: pdfRest API key
PDFREST_API_KEY=your_api_key_here

# Optional: API base URL
# - Default (US): https://api.pdfrest.com
# - EU/GDPR region: https://eu-api.pdfrest.com
PDFREST_URL=https://api.pdfrest.com
# For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
94 changes: 94 additions & 0 deletions DotNET/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Repository Guidelines

## Project Structure & Module Organization
- DotNET samples are organized by scenario:
- `Endpoint Examples/Multipart Payload`: send files + params via `multipart/form-data`.
- `Endpoint Examples/JSON Payload`: upload files then call endpoints with JSON.
- `Complex Flow Examples`: multi‑step workflows across endpoints.
- Recommended: a single .NET 8 console app project that dispatches to these samples via a command.

## Build, Run, and Environment
- Prereq: .NET 8 SDK (`dotnet --version`).
- Included here:
- `DotNetSamples.csproj` wired to `Program.cs` (dispatcher).
- `.env.example` template for local configuration.
- Environment config (mirrors VB.NET):
- Copy `.env.example` to `.env` and set `PDFREST_API_KEY=...`.
- Optional: `PDFREST_URL=https://eu-api.pdfrest.com` for EU/GDPR; default is `https://api.pdfrest.com`.
- Run commands from this folder:
- `dotnet build`
- `dotnet run -- markdown-json /path/to/input.pdf`
- `dotnet run -- rasterized-pdf /path/to/input.pdf`
- `dotnet run -- pdf-multipart /path/to/input.html text/html`
- `dotnet run -- merge-different-file-types image.png slides.ppt`
- `dotnet run -- extracted-text /path/to/input.pdf`
- `dotnet run -- extracted-images /path/to/input.pdf`
- `dotnet run -- pdf-info /path/to/input.pdf`
- `dotnet run -- merged-pdf file1.pdf file2.pdf`
- `dotnet run -- split-pdf /path/to/input.pdf`
- `dotnet run -- upload /path/to/input.pdf`
- `dotnet run -- get-resource <id> [out]`
- `dotnet run -- delete-resource <id>`
- `dotnet run -- batch-delete <id1> [id2] [...]`
- `.env` loading: uses `DotNetEnv` (`Env.Load()`), matching VB.NET.

Note: The project currently compiles only `Program.cs` and `Endpoint Examples/JSON Payload/markdown.cs` to avoid top‑level statement conflicts. To enable more samples, add them explicitly to `DotNetSamples.csproj` under a `<Compile Include="..." />` item or refactor them into classes with `Execute(string[] args)`.

Why no solution file?
- This folder contains a single project; removing the `.sln` lets `dotnet build` and `dotnet run` infer the project automatically. If you later add multiple projects, reintroduce a solution or pass `--project` explicitly.

## Coding Style & Naming Conventions
- C# 12 / .NET 8; 4‑space indentation; minimal, single‑responsibility methods.
- Filenames: kebab‑case describing action (e.g., `pdf-with-ocr-text.cs`).
- HTTP: use `HttpClient` with `Api-Key` header; base URL from `PDFREST_URL` to support region selection.
- Prefer low-indentation patterns:
- File-scoped namespaces (`namespace X.Y;`).
- `using var` for disposables instead of nested `using (...) {}` blocks.

## Testing Guidelines
- No unit tests here; validate by running commands and inspecting JSON output.
- For binary endpoints, write bytes to disk and manually verify (open PDF/image).

## Adapting Samples (Minimal Changes)
- Keep the original I/O style: if a sample uses sync calls, keep them sync; if it uses async/await, keep it async.
- Wrap in a small shim so Program.cs can call it:
- `namespace Samples.<FolderPath>;`
- `public static class <SampleName> { public static <void|Task> Execute(string[] args) { /* existing code */ } }`
- Replace literals with environment/args only:
- API key: `Environment.GetEnvironmentVariable("PDFREST_API_KEY")`
- Base URL: `Environment.GetEnvironmentVariable("PDFREST_URL") ?? "https://api.pdfrest.com"`
- Input path: take from `args[0]` and use for `Content-Filename`.
- Opt the file into the project by adding `<Compile Include="…" />` to `DotNetSamples.csproj`.
- Always insert the Sample Header Template at the very beginning of the file (before any `using` lines).

## Sample Header Template
Use this comment block at the TOP of each sample file you adapt for dispatching — place it before any `using` directives or namespace (keep lines concise and include the GDPR info line):

```
/*
* What this sample does:
* - Brief description… (how it’s called from Program.cs)
*
* Setup (environment):
* - Copy .env.example to .env
* - Set PDFREST_API_KEY=your_api_key_here
* - Optional: set PDFREST_URL to override the API region. For EU/GDPR compliance and proximity, use:
* PDFREST_URL=https://eu-api.pdfrest.com
* For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
*
* Usage:
* dotnet run -- <command> [args]
*
* Output:
* - Describe output and error behavior.
*/
```

## Commit & Pull Request Guidelines
- Commits: concise, scoped to a sample or infra. Prefixes: `feat(sample)`, `fix(sample)`, `chore(env)`, `docs(dotnet)`.
- PRs include: purpose, endpoints, run example (`dotnet run -- <command>`), assumptions (paths/content types), and sample output.

## Security & Region/GDPR Tips
- Never commit secrets or `.env`; provide `.env.example` only.
- Prefer `DotNetEnv` + `Environment.GetEnvironmentVariable` for keys/URLs.
- EU/GDPR: set `PDFREST_URL=https://eu-api.pdfrest.com` to keep data in-region; default is `https://api.pdfrest.com`.
205 changes: 111 additions & 94 deletions DotNET/Complex Flow Examples/decrypt-add-reencrypt.cs
Original file line number Diff line number Diff line change
@@ -1,99 +1,116 @@
/*
* What this sample does:
* - Decrypts a PDF, adds an image, then re-encrypts it.
* - Routed from Program.cs as: `dotnet run -- decrypt-add-reencrypt <pdf> <image> [password]`.
*
* Setup (environment):
* - Copy .env.example to .env
* - Set PDFREST_API_KEY=your_api_key_here
* - Optional: set PDFREST_URL to override the API region. For EU/GDPR compliance and proximity, use:
* PDFREST_URL=https://eu-api.pdfrest.com
* For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
*
* Usage:
* dotnet run -- decrypt-add-reencrypt input.pdf image.png secret
*
* Output:
* - Prints JSON responses for decrypt, add-image, and re-encrypt stages.
*/

using Newtonsoft.Json.Linq;
using System.Text;

/* In this sample, we will show how to take an encrypted file and decrypt, modify
* and re-encrypt it to create an encryption-at-rest solution as discussed in
* https://pdfrest.com/solutions/create-secure-document-workflows-with-pdf-password-protection/
* We will be running the document through /decrypted-pdf to open the document
* to modification, running the decrypted result through /pdf-with-added-image,
* and then sending the output with the new image through /encrypted-pdf to
* lock it up again.
*/

var apiKey = "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Your API key here

using (var httpClient = new HttpClient { BaseAddress = new Uri("https://api.pdfrest.com") })
namespace Samples.ComplexFlowExamples
{
// Begin decryption
using var decryptRequest = new HttpRequestMessage(HttpMethod.Post, "decrypted-pdf");

decryptRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
decryptRequest.Headers.Accept.Add(new("application/json"));
var decryptMultipartContent = new MultipartFormDataContent();

var byteArray = File.ReadAllBytes("/path/to/file.pdf");
var byteAryContent = new ByteArrayContent(byteArray);
decryptMultipartContent.Add(byteAryContent, "file", "file.pdf");
byteAryContent.Headers.TryAddWithoutValidation("Content-Type", "application/pdf");

var byteArrayOption = new ByteArrayContent(Encoding.UTF8.GetBytes("password"));
decryptMultipartContent.Add(byteArrayOption, "current_open_password");


decryptRequest.Content = decryptMultipartContent;
var decryptResponse = await httpClient.SendAsync(decryptRequest);

var decryptResult = await decryptResponse.Content.ReadAsStringAsync();

Console.WriteLine("Decrypt response received.");
Console.WriteLine(decryptResult);

dynamic decryptJson = JObject.Parse(decryptResult);
string decryptID = decryptJson.outputId;

// Begin add image
using var addImageRequest = new HttpRequestMessage(HttpMethod.Post, "pdf-with-added-image");

addImageRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
addImageRequest.Headers.Accept.Add(new("application/json"));
var addImageMultipartContent = new MultipartFormDataContent();

var addImageId = new ByteArrayContent(Encoding.UTF8.GetBytes(decryptID));
addImageMultipartContent.Add(addImageId, "id");

var addImageImage = File.ReadAllBytes("/path/to/file.png");
var imageContent = new ByteArrayContent(addImageImage);
addImageMultipartContent.Add(imageContent, "image_file", "file_name.png");
imageContent.Headers.TryAddWithoutValidation("Content-Type", "image/png");

var addImagePage = new ByteArrayContent(Encoding.UTF8.GetBytes("1"));
addImageMultipartContent.Add(addImagePage, "page");

var addImageX = new ByteArrayContent(Encoding.UTF8.GetBytes("0"));
addImageMultipartContent.Add(addImageX, "x");
var addImageY = new ByteArrayContent(Encoding.UTF8.GetBytes("0"));
addImageMultipartContent.Add(addImageY, "y");

addImageRequest.Content = addImageMultipartContent;
var addImageResponse = await httpClient.SendAsync(addImageRequest);

using var addImageResult = await addImageResponse.Content.ReadAsStringAsync();

Console.WriteLine("Add image response received.");
Console.WriteLine(addImageResult);

dynamic addImageJson = JObject.Parse(addImageResult);
string addImageID = addImageJson.outputId;

// Begin re-encryption
var encryptRequest = new HttpRequestMessage(HttpMethod.Post, "encrypted-pdf");

encryptRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
encryptRequest.Headers.Accept.Add(new("application/json"));
var multipartContent = new MultipartFormDataContent();

var encryptID = new ByteArrayContent(Encoding.UTF8.GetBytes(addImageID));
multipartContent.Add(encryptID, "id");

var encryptPassword = new ByteArrayContent(Encoding.UTF8.GetBytes("password"));
multipartContent.Add(encryptPassword, "new_open_password");


encryptRequest.Content = multipartContent;
var response = await httpClient.SendAsync(encryptRequest);

var apiResult = await response.Content.ReadAsStringAsync();

Console.WriteLine("Encrypt response received.");
Console.WriteLine(apiResult);
public static class DecryptAddReencrypt
{
public static async Task Execute(string[] args)
{
if (args == null || args.Length < 2)
{
Console.Error.WriteLine("decrypt-add-reencrypt requires <pdf> <image> [password]");
Environment.Exit(1);
return;
}
var pdfPath = args[0];
var imgPath = args[1];
var pwd = args.Length > 2 ? args[2] : "password";
if (!File.Exists(pdfPath) || !File.Exists(imgPath))
{
Console.Error.WriteLine("One or more input files not found.");
Environment.Exit(1);
return;
}
var apiKey = Environment.GetEnvironmentVariable("PDFREST_API_KEY");
if (string.IsNullOrWhiteSpace(apiKey))
{
Console.Error.WriteLine("Missing required environment variable: PDFREST_API_KEY");
Environment.Exit(1);
return;
}
var baseUrl = Environment.GetEnvironmentVariable("PDFREST_URL") ?? "https://api.pdfrest.com";

using (var httpClient = new HttpClient { BaseAddress = new Uri(baseUrl) })
{
// Decrypt
using var decryptRequest = new HttpRequestMessage(HttpMethod.Post, "decrypted-pdf");
decryptRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
decryptRequest.Headers.Accept.Add(new("application/json"));
var decryptMultipartContent = new MultipartFormDataContent();
var byteArray = File.ReadAllBytes(pdfPath);
var byteAryContent = new ByteArrayContent(byteArray);
decryptMultipartContent.Add(byteAryContent, "file", Path.GetFileName(pdfPath));
byteAryContent.Headers.TryAddWithoutValidation("Content-Type", "application/octet-stream");
var byteArrayOption = new ByteArrayContent(Encoding.UTF8.GetBytes(pwd));
decryptMultipartContent.Add(byteArrayOption, "current_open_password");
decryptRequest.Content = decryptMultipartContent;
var decryptResponse = await httpClient.SendAsync(decryptRequest);
var decryptResult = await decryptResponse.Content.ReadAsStringAsync();
Console.WriteLine("Decrypt response received.");
Console.WriteLine(decryptResult);
dynamic decryptJson = JObject.Parse(decryptResult);
string decryptID = decryptJson.outputId;

// Add image
using var addImageRequest = new HttpRequestMessage(HttpMethod.Post, "pdf-with-added-image");
addImageRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
addImageRequest.Headers.Accept.Add(new("application/json"));
var addImageMultipartContent = new MultipartFormDataContent();
var addImageId = new ByteArrayContent(Encoding.UTF8.GetBytes(decryptID));
addImageMultipartContent.Add(addImageId, "id");
var addImageImage = File.ReadAllBytes(imgPath);
var imageContent = new ByteArrayContent(addImageImage);
addImageMultipartContent.Add(imageContent, "image_file", Path.GetFileName(imgPath));
imageContent.Headers.TryAddWithoutValidation("Content-Type", "application/octet-stream");
var addImagePage = new ByteArrayContent(Encoding.UTF8.GetBytes("1"));
addImageMultipartContent.Add(addImagePage, "page");
var addImageX = new ByteArrayContent(Encoding.UTF8.GetBytes("0"));
addImageMultipartContent.Add(addImageX, "x");
var addImageY = new ByteArrayContent(Encoding.UTF8.GetBytes("0"));
addImageMultipartContent.Add(addImageY, "y");
addImageRequest.Content = addImageMultipartContent;
var addImageResponse = await httpClient.SendAsync(addImageRequest);
var addImageResult = await addImageResponse.Content.ReadAsStringAsync();
Console.WriteLine("Add image response received.");
Console.WriteLine(addImageResult);
dynamic addImageJson = JObject.Parse(addImageResult);
string addImageID = addImageJson.outputId;

// Re-encrypt
using var encryptRequest = new HttpRequestMessage(HttpMethod.Post, "encrypted-pdf");
encryptRequest.Headers.TryAddWithoutValidation("Api-Key", apiKey);
encryptRequest.Headers.Accept.Add(new("application/json"));
var multipartContent = new MultipartFormDataContent();
var encryptID = new ByteArrayContent(Encoding.UTF8.GetBytes(addImageID));
multipartContent.Add(encryptID, "id");
var encryptPassword = new ByteArrayContent(Encoding.UTF8.GetBytes(pwd));
multipartContent.Add(encryptPassword, "new_open_password");
encryptRequest.Content = multipartContent;
var response = await httpClient.SendAsync(encryptRequest);
var apiResult = await response.Content.ReadAsStringAsync();
Console.WriteLine("Encrypt response received.");
Console.WriteLine(apiResult);
}
}
}
}
Loading