How to Convert CSV to PDF in .NET with C#
This .NET walkthrough shows how C# can transform CSV data into a styled, tagged PDF table with the pdfRest Convert to PDF API Tool. The request defines column widths and alignment along with header, border, row, padding, and pagination behavior.
Why Convert CSV to PDF in .NET with C#?
Line-of-business .NET applications often receive CSV exports from ERP, manufacturing, and finance platforms. Although users can open those files in spreadsheet software, the raw export does not provide a controlled layout for approval packets, shift records, or management review.
A production system might export work-center names, exception descriptions, and affected-unit counts at the end of each shift. C# can convert the file into a PDF with a broad description column, right-aligned counts, and repeating headers. The report then fits naturally beside other PDF records for the shift without an operator reformatting the data.
This automation makes the generated document reproducible. Table colors, border rules, spacing, page margins, metadata, and tagging come from application-owned options instead of a workbook that can be changed accidentally.
C# Code Example for Converting CSV to PDF
/* * What this sample does: * - Converts structured CSV input to PDF through the /pdf endpoint. * * Setup (environment): * - Set PDFREST_API_KEY=your_api_key_here * - Optional: set PDFREST_URL to override the API region. * * Usage: * dotnet run -- pdf-from-csv-multipart*/ using Newtonsoft.Json.Linq; using System.Net.Http.Headers; using System.Text; namespace Samples.EndpointExamples.MultipartPayload; public static class PdfFromCsv { public static async Task Execute(string[] args) { var inputPath = args.Length > 0 ? args[0] : "/path/to/sample.csv"; var apiKey = Environment.GetEnvironmentVariable("PDFREST_API_KEY"); if (string.IsNullOrWhiteSpace(apiKey)) throw new InvalidOperationException("Missing PDFREST_API_KEY"); var baseUrl = Environment.GetEnvironmentVariable("PDFREST_URL") ?? "https://api.pdfrest.com"; using var client = new HttpClient { BaseAddress = new Uri(baseUrl) }; client.DefaultRequestHeaders.TryAddWithoutValidation("Api-Key", apiKey); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var options = JObject.Parse(@"{""title"":""Structured Content Sample"",""language"":""en-US"",""enable_tagging"":true,""page_setup"":{""size"":""Letter"",""orientation"":""portrait"",""margin"":{""top"":36,""right"":42,""bottom"":36,""left"":42}},""style"":{""font"":""Arial"",""heading_font"":""Arial"",""code_font"":""Courier"",""text_size"":11,""text_color_rgb"":[34,34,34],""heading_scale"":1.35,""table"":{""column_width_weights"":[2,3,2],""keep_header_with_first_row"":true,""repeat_headers_on_overflow"":true,""show_borders"":true,""border_width"":0.75,""border_color_rgb"":[180,188,200],""header_fill_color_rgb"":[33,64,98],""header_text_color_rgb"":[255,255,255],""row_fill_color_rgb"":[250,250,252],""alternate_row_fill_color_rgb"":[235,240,246],""cell_padding"":{""top"":6,""right"":8,""bottom"":6,""left"":8}}},""csv"":{""first_row_is_header"":true,""delimiter"":"","",""columns"":[{""index"":0,""width_weight"":2,""text_align"":""left""},{""index"":1,""width_weight"":3,""text_align"":""left""},{""index"":2,""width_weight"":1,""text_align"":""right""}]}}"); using var form = new MultipartFormDataContent(); var inputContent = new ByteArrayContent(await File.ReadAllBytesAsync(inputPath)); inputContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); form.Add(inputContent, "file", Path.GetFileName(inputPath)); form.Add(new StringContent(options.ToString()), "structured_text_options"); var response = await client.PostAsync("pdf", form); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); if (!response.IsSuccessStatusCode) Environment.ExitCode = 1; } }
Source: View the sample on GitHub
Breaking Down the Code
The C# CSV sample uses the framework HttpClient APIs and Newtonsoft JSON types for structured_text_options. A project adopting this code must retain the Newtonsoft.Json package reference used by the samples repository.
using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient { BaseAddress = new Uri(baseUrl) };
using var form = new MultipartFormDataContent();
The .NET endpoint block shows which regional service receives this CSV request:
if (string.IsNullOrWhiteSpace(apiKey)) throw new InvalidOperationException("Missing PDFREST_API_KEY");
var baseUrl = Environment.GetEnvironmentVariable("PDFREST_URL") ?? "https://api.pdfrest.com";
using var client = new HttpClient { BaseAddress = new Uri(baseUrl) };
client.DefaultRequestHeaders.TryAddWithoutValidation("Api-Key", apiKey);
C# turns the .csv source into StreamContent and preserves its filename in the multipart part. That extension directs the shared /pdf endpoint to the CSV converter.
{
var inputPath = args.Length > 0 ? args[0] : "/path/to/sample.csv";
var apiKey = Environment.GetEnvironmentVariable("PDFREST_API_KEY");
The Newtonsoft JObject represents pdfRest’s structured conversion settings. It defines the output title and language, explicitly enables tags, configures Letter portrait pages and margins, and carries the typography and CSV-related style properties used by the renderer.
{
"csv": {
"first_row_is_header": true,
"delimiter": ",",
"columns": [
{
"index": 0,
"width_weight": 2,
"text_align": "left"
},
{
"index": 1,
"width_weight": 3,
"text_align": "left"
},
{
"index": 2,
"width_weight": 1,
"text_align": "right"
}
]
}
}
first_row_is_header defaults to true; setting it to false renders every record as a body row. delimiter defaults to a comma and must contain exactly one character, so a tab or semicolon can be selected but a multi-character separator cannot.
Column indexes are zero-based. Unspecified columns default to weight 1 and left alignment. Width weights are positive relative proportions, not points or pixels, and text_align accepts only left, center, or right. An index outside the parsed CSV, a nonpositive weight, or another alignment value produces a validation error.
The per-column CSV weights take precedence over style.table.column_width_weights; the broader table list is only a fallback when CSV-specific widths are absent. The remaining table style controls borders, colors, row striping, and padding. keep_header_with_first_row prevents a header from appearing alone, and repeat_headers_on_overflow repeats it as rows continue onto later pages.
For CSV, MultipartFormDataContent owns the source stream, serialized settings, and output field. HttpClient generates the matching multipart boundary and content type when it sends the container.
var inputContent = new ByteArrayContent(await File.ReadAllBytesAsync(inputPath));
inputContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(inputContent, "file", Path.GetFileName(inputPath));
form.Add(new StringContent(options.ToString()), "structured_text_options");
var response = await client.PostAsync("pdf", form);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
if (!response.IsSuccessStatusCode) Environment.ExitCode = 1;
}
}
The C# client authenticates and posts the CSV form, then reads the response as text. Reporting both status and payload lets an integration distinguish a generated PDF resource from validation or processing errors.
var inputContent = new ByteArrayContent(await File.ReadAllBytesAsync(inputPath));
inputContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(inputContent, "file", Path.GetFileName(inputPath));
form.Add(new StringContent(options.ToString()), "structured_text_options");
var response = await client.PostAsync("pdf", form);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
if (!response.IsSuccessStatusCode) Environment.ExitCode = 1;
}
}
Beyond the Tutorial
Useful adaptations include quality-control lists, production summaries, ledger extracts, and service-level reports. Column definitions can be tailored to each export while the larger document style remains consistent across the organization.
The requested tags describe table relationships for compatible consumers but do not guarantee PDF/UA or WCAG compliance. Prototype the table in API Lab and consult the Convert to PDF documentation for validation requirements and option details.