pub fn generate_pdf_from_html(
pool: &Mutex<BrowserPool>,
request: &PdfFromHtmlRequest,
) -> Result<PdfResponse, PdfServiceError>Expand description
Generate a PDF from HTML content.
Loads the provided HTML content into a browser tab using a data URL, waits for any JavaScript execution, and generates a PDF.
§Thread Safety
This function is thread-safe and can be called concurrently from multiple
threads. See generate_pdf_from_url for details.
§Blocking Behavior
This function blocks the calling thread. See generate_pdf_from_url
for guidance on async usage.
§How It Works
The HTML content is converted to a data URL:
data:text/html;charset=utf-8,<encoded-html-content>This allows loading HTML directly without a web server. The browser renders the HTML as if it were loaded from a regular URL.
§Arguments
pool- Reference to the mutex-wrapped browser poolrequest- HTML content and generation parameters. SeePdfFromHtmlRequest.
§Returns
Ok(PdfResponse)- Successfully generated PDFErr(PdfServiceError)- Error details
§Errors
| Error | Cause | Resolution |
|---|---|---|
EmptyHtml | HTML content is empty/whitespace | Provide HTML content |
PoolLockFailed | Mutex poisoned | Restart service |
BrowserUnavailable | Pool exhausted | Retry or increase pool size |
NavigationFailed | HTML parsing issue | Check HTML validity |
PdfGenerationFailed | Rendering issue | Simplify HTML |
§Limitations
§External Resources
Since HTML is loaded via data URL, relative URLs don’t work:
<!-- ❌ Won't work - relative URL -->
<img src="/images/logo.png">
<!-- ✅ Works - absolute URL -->
<img src="https://example.com/images/logo.png">
<!-- ✅ Works - inline base64 -->
<img src="data:image/png;base64,iVBORw0KGgo...">§Size Limits
Data URLs have browser-specific size limits. For very large HTML documents (> 1MB), consider:
- Hosting the HTML on a temporary server
- Using
generate_pdf_from_urlinstead - Splitting into multiple PDFs
§Examples
§Simple HTML
ⓘ
use html2pdf_api::service::{generate_pdf_from_html, PdfFromHtmlRequest};
let request = PdfFromHtmlRequest {
html: "<h1>Hello World</h1><p>This is a test.</p>".to_string(),
..Default::default()
};
let response = generate_pdf_from_html(&pool, &request)?;
std::fs::write("output.pdf", &response.data)?;§Complete Document with Styling
ⓘ
let html = r#"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body {
font-family: 'Arial', sans-serif;
margin: 40px;
color: #333;
}
h1 {
color: #0066cc;
border-bottom: 2px solid #0066cc;
padding-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
th {
background-color: #f5f5f5;
}
</style>
</head>
<body>
<h1>Monthly Report</h1>
<p>Generated on: 2024-01-15</p>
<table>
<tr><th>Metric</th><th>Value</th></tr>
<tr><td>Revenue</td><td>$50,000</td></tr>
<tr><td>Users</td><td>1,234</td></tr>
</table>
</body>
</html>
"#;
let request = PdfFromHtmlRequest {
html: html.to_string(),
filename: Some("monthly-report.pdf".to_string()),
print_background: Some(true), // Include styled backgrounds
..Default::default()
};
let response = generate_pdf_from_html(&pool, &request)?;§With Embedded Images
ⓘ
// Base64 encode an image
let image_base64 = base64::encode(std::fs::read("logo.png")?);
let html = format!(r#"
<!DOCTYPE html>
<html>
<body>
<img src="data:image/png;base64,{}" alt="Logo">
<h1>Company Report</h1>
</body>
</html>
"#, image_base64);
let request = PdfFromHtmlRequest {
html,
..Default::default()
};
let response = generate_pdf_from_html(&pool, &request)?;