Don't waste your day reinventing the wheel, be converting in 3 minutes from now
If you are looking for a C# webpage to pdf converter, you can use our free web service, in use by commercial applications and platforms. You do not need to install or download any libraries or components to make this work.
Especially great for reporting, brochures and invoicing - create one HTML webpage and use it as both as a source to generate your downloadable PDF or for users to view directly.
The service will convert webpages to pdfs online by reading your webpage and dynamically generate a PDF or an image. It will handle fairly complex documents and layouts including images and executing javascript, although as always the simpler the better.
See example #5 for a the new ASPNET 5 code.
By commenting out line #17 you can switch between showing the file inside the browser window itself (if supported by the browser), and downloading as an attachment.
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
public class PdfController : Controller | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
public async Task<IActionResult> Run() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "http://www.google.com"; // URL or HTML string | |
var formData = new Dictionary<string, string> | |
{ | |
{ "apikey", apiKey }, | |
{ "value", value } | |
}; | |
using (var content = new FormUrlEncodedContent(formData)) | |
{ | |
HttpResponseMessage response = await httpClient.PostAsync("https://api.html2pdfrocket.com/pdf", content); | |
response.EnsureSuccessStatusCode(); | |
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync(); | |
MemoryStream ms = new MemoryStream(pdfBytes); | |
return File(ms, "application/pdf", "myfilename.pdf"); | |
} | |
} | |
} |
Line #12 allows you to change the default output format so the html is converted into an image. You can use "png", "bmp" or "svg" formats for images. You could add line #12 to the above example to steam the image to the user (or as an attachment), or you can use this example which instead saves the image to your disk.
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
public class ImageConverter | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
public async Task ConvertToImage() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "http://www.google.com"; // URL or HTML string | |
var formData = new Dictionary<string, string> | |
{ | |
{ "apikey", apiKey }, | |
{ "value", value }, | |
{ "OutputFormat", "jpg" } | |
}; | |
using (var content = new FormUrlEncodedContent(formData)) | |
{ | |
// Call the API to convert to image | |
HttpResponseMessage response = await httpClient.PostAsync("https://api.html2pdfrocket.com/pdf", content); | |
response.EnsureSuccessStatusCode(); | |
// Read response as byte array and save as an image | |
byte[] imageBytes = await response.Content.ReadAsByteArrayAsync(); | |
await File.WriteAllBytesAsync(@"C:\temp\myimage.jpg", imageBytes); | |
} | |
} | |
} |
You can also convert an HTML string to a PDF by supplying the HTML directly. It can be as complex as you like and may include image references and stylesheeet information -- just make sure it is valid HTML
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
public class PdfGenerator | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
public async Task GeneratePdf() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "<h1>An <strong>Example</strong>HTML String</h1>"; // Direct HTML string | |
var formData = new Dictionary<string, string> | |
{ | |
{ "apikey", apiKey }, | |
{ "value", value } | |
}; | |
using (var content = new FormUrlEncodedContent(formData)) | |
{ | |
// Call the API to convert to PDF | |
HttpResponseMessage response = await httpClient.PostAsync("https://api.html2pdfrocket.com/pdf", content); | |
response.EnsureSuccessStatusCode(); | |
// Read response as byte array and save to file | |
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync(); | |
await File.WriteAllBytesAsync(@"C:\temp\mypdf.pdf", pdfBytes); | |
} | |
} | |
public async Task DownloadFile() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "http://www.google.com"; // A URL starting with http or an HTML string | |
string requestUrl = $"https://api.html2pdfrocket.com/pdf?apikey={Uri.EscapeDataString(apiKey)}&value={Uri.EscapeDataString(value)}"; | |
byte[] pdfBytes = await httpClient.GetByteArrayAsync(requestUrl); | |
await File.WriteAllBytesAsync(@"C:\temp\mypdf.pdf", pdfBytes); | |
} | |
} |
By default page margins are set to zero. In this example, we increase the bottom margin to 30 to allow space for a page footer. Note you could use a Url to the file, or you could pass the whole file as a string with the FooterHtml parameter
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
public class PdfController : Controller | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
public async Task<IActionResult> TestC() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "http://www.google.com"; | |
// Prepare form data | |
var formData = new Dictionary<string, string> | |
{ | |
{ "apikey", apiKey }, | |
{ "value", value }, | |
{ "MarginBottom", "30" }, | |
{ "FooterUrl", "https://html2pdfrocket.com/examples/footer.htm" } | |
}; | |
using (var content = new FormUrlEncodedContent(formData)) | |
{ | |
// Call the API to convert to PDF | |
HttpResponseMessage response = await httpClient.PostAsync("https://api.html2pdfrocket.com/pdf", content); | |
response.EnsureSuccessStatusCode(); | |
// Read response as a byte array | |
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync(); | |
// Return the file as a downloadable attachment | |
return File(pdfBytes, "application/pdf", "sample.pdf"); | |
} | |
} | |
} |
<!DOCTYPE html> | |
<html> | |
<head> | |
<script> | |
function subst() { | |
var vars = {}; | |
var x = window.location.search.substring(1).split('&'); | |
for (var i in x) { var z = x[i].split('=', 2); vars[z[0]] = unescape(z[1]); } | |
var x = ['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection']; | |
for (var i in x) { | |
var y = document.getElementsByClassName(x[i]); | |
for (var j = 0; j < y.length; ++j) y[j].textContent = vars[x[i]]; | |
} | |
} | |
</script> | |
</head> | |
<body style="border:0; margin: 0;" onload="subst()"> | |
<table style="border-bottom: 1px solid black; width: 100%"> | |
<tr> | |
<td class="section"></td> | |
<td style="text-align:right"> | |
Page <span class="page"></span> of <span class="topage"></span> | |
</td> | |
</tr> | |
</table> | |
</body> | |
</html> |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
<script> | |
function subst() { | |
var vars = {}; | |
var x = document.location.search.substring(1).split('&'); | |
for (var i in x) { var z = x[i].split('=', 2); vars[z[0]] = unescape(z[1]); } | |
var x = ['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection']; | |
for (var i in x) { | |
var y = document.getElementsByClassName(x[i]); | |
for (var j = 0; j < y.length; ++j) y[j].textContent = vars[x[i]]; | |
if (vars['page'] == 1) { // If page is 1, set FakeHeaders display to none | |
document.getElementById("FakeHeaders").style.display = 'none'; | |
} | |
if (vars['page'] == 3) { // If page is 3, set FakeHeaders display to none | |
document.getElementById("FakeHeaders").style.display = 'none'; | |
} | |
} | |
} | |
</script> | |
</head> | |
<body style="border:0;margin:0;" onload="subst()"> | |
<table style="border-bottom: 1px solid pink; width: 100%; margin-bottom:5px;" id="FakeHeaders"> | |
<tr> | |
<th>Your awesome table column header 1</th> | |
<th>Column 2</th> | |
<th style="text-align:right"> | |
Page <span class="page"></span>/<span class="topage"></span> | |
</th> | |
</tr> | |
</table> | |
</body> | |
</html> |
Line #20 allows you to stream the bytes directly to the browser to use as an attachment
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
public class PdfController : Controller | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
public async Task<IActionResult> Run() | |
{ | |
string apiKey = "YOUR-API-KEY"; | |
string value = "http://www.google.com"; // URL or HTML string | |
// Prepare form data | |
var formData = new Dictionary<string, string> | |
{ | |
{ "apikey", apiKey }, | |
{ "value", value } | |
}; | |
using (var content = new FormUrlEncodedContent(formData)) | |
{ | |
// Call the API to convert to PDF | |
HttpResponseMessage response = await httpClient.PostAsync("https://api.html2pdfrocket.com/pdf", content); | |
response.EnsureSuccessStatusCode(); | |
// Read response as a byte array | |
byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync(); | |
// Return the file as a PDF | |
return File(pdfBytes, "application/pdf", "myfilename.pdf"); | |
} | |
} | |
} |
The WebClient has been replaced with HttpClient in ASP.NET 5. Other aspects follow the same format.
using (var client = new HttpClient()) | |
{ | |
var param = new Dictionary<string, string>(); | |
param.Add("apikey", apiKey); | |
param.Add("value", url); | |
var content = new FormUrlEncodedContent(param); | |
var result = client.PostAsync("https://api.html2pdfrocket.com/pdf", content).Result; | |
if (result.IsSuccessStatusCode) | |
{ | |
MemoryStream stream = new MemoryStream(result.Content.ReadAsByteArrayAsync().Result); | |
return File(stream, "application/pdf", "MyPdfFile.pdf"); | |
} | |
} |
For PDF conversion taking more than 30 seconds or input/output files more than 6 Mb, you need to use the batch/asynchronous parameters.
using (var client = new HttpClient()) | |
{ | |
var param = new Dictionary<string, string>(); | |
param.Add("apikey", apiKey); | |
param.Add("value", url); | |
param.Add("Batch", "true"); | |
//as an alternative to polling, you can pass the webhook option parameter | |
//from your website where the api could post back once the pdf file is ready | |
//the same JSON Result is posted back with Status=Ready and the PDFLink | |
param.Add("Webhook", "https://b2b-example.customer.com/my-webhook"); | |
var content = new FormUrlEncodedContent(param); | |
var result = client.PostAsync(apiUrl, content).Result; | |
if (result.IsSuccessStatusCode) | |
{ | |
string jsonResult = result.Content.ReadAsStringAsync().Result; | |
JObject jsonParsed = JObject.Parse(jsonResult); | |
if (jsonParsed["PdfToken"] != null) | |
{ | |
string pdfToken = jsonParsed["PdfToken"].ToString(); | |
param.Add("PdfToken", pdfToken); | |
content = new FormUrlEncodedContent(param); | |
//polling every 30 seconds to check if the pdf file is ready | |
do | |
{ | |
result = client.PostAsync(apiUrl, content).Result; | |
jsonResult = result.Content.ReadAsStringAsync().Result; | |
jsonParsed = JObject.Parse(jsonResult); | |
string status = ""; | |
if (jsonParsed["Status"] != null) | |
status = jsonParsed["Status"].ToString(); | |
if (status == "Ready") | |
{ | |
File.WriteAllBytes("MyPdfFile.pdf", client.GetByteArrayAsync(jsonParsed["PdfLink"].ToString()).Result); | |
break; | |
} | |
else | |
{ | |
//wait for 30 seconds | |
System.Threading.Thread.Sleep(30000); | |
} | |
} while (true); | |
} | |
} | |
} |
Need another C# example? Would you mind dropping us a quick one line note to say which example you would have liked and we'll put the most commonly used ones here.
Don't waste your day reinventing the wheel, be converting in 3 minutes from now
The number #1 reason a conversion fails to look correct is because it contains an references to external links or images that don't exist, or exist on your localhost. If there is a conversion error, please check the page using your webbrowsers 'developer' network tab to ensure there are no 404 errors.