C# 및 .NET에서 스크린샷을 찍고 PDF를 생성하는 방법
Source: Dev.to
위에 제공된 소스 링크 외에 번역할 텍스트가 포함되어 있지 않습니다. 번역을 원하는 본문을 제공해 주시면 한국어로 번역해 드리겠습니다.
URL의 스크린샷
using System.Net.Http;
using System.Text;
using System.Text.Json;
public class PageBoltClient
{
private static readonly HttpClient _http = new();
private readonly string _apiKey = Environment.GetEnvironmentVariable("PAGEBOLT_API_KEY")!;
private const string BaseUrl = "https://pagebolt.dev/api/v1";
public async Task<byte[]> ScreenshotAsync(string url)
{
var body = JsonSerializer.Serialize(new
{
url,
fullPage = true,
blockBanners = true
});
using var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/screenshot");
request.Headers.Add("x-api-key", _apiKey);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await _http.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsByteArrayAsync();
}
}
URL에서 PDF
public async Task<byte[]> PdfFromUrlAsync(string url)
{
var body = JsonSerializer.Serialize(new { url, blockBanners = true });
using var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/pdf");
request.Headers.Add("x-api-key", _apiKey);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await _http.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsByteArrayAsync();
}
HTML에서 PDF 생성 (PuppeteerSharp / wkhtmltopdf 대체)
public async Task<byte[]> PdfFromHtmlAsync(string html)
{
var body = JsonSerializer.Serialize(new { html });
using var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/pdf");
request.Headers.Add("x-api-key", _apiKey);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await _http.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsByteArrayAsync();
}
System.Text.Json.JsonSerializer.Serialize는 모든 이스케이프 처리를 수행합니다 — 수동으로 문자열을 만들 필요가 없습니다.
DI에서 싱글톤으로 등록 (권장)
// Program.cs
builder.Services.AddHttpClient();
builder.Services.AddSingleton<PageBoltClient>();
// PageBoltClient.cs — 생성자 주입 버전
public class PageBoltClient
{
private readonly HttpClient _http;
private readonly string _apiKey;
private const string BaseUrl = "https://pagebolt.dev/api/v1";
public PageBoltClient(HttpClient http, IConfiguration config)
{
_http = http;
_apiKey = config["PageBolt:ApiKey"]
?? throw new InvalidOperationException("PageBolt:ApiKey not configured");
}
public async Task<byte[]> ScreenshotAsync(string url) { /* … */ }
public async Task<byte[]> PdfFromHtmlAsync(string html) { /* … */ }
}
ASP.NET Core 컨트롤러
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/invoices")]
public class InvoiceController : ControllerBase
{
private readonly PageBoltClient _pagebolt;
private readonly IInvoiceService _invoices;
private readonly IRazorViewRenderer _renderer;
public InvoiceController(
PageBoltClient pagebolt,
IInvoiceService invoices,
IRazorViewRenderer renderer)
{
_pagebolt = pagebolt;
_invoices = invoices;
_renderer = renderer;
}
[HttpGet("{id}/pdf")]
public async Task<IActionResult> DownloadPdf(int id)
{
var invoice = await _invoices.GetByIdAsync(id);
var html = await _renderer.RenderAsync("Invoice", invoice);
var pdf = await _pagebolt.PdfFromHtmlAsync(html);
return File(pdf, "application/pdf", $"invoice-{id}.pdf");
}
[HttpGet("{id}/screenshot")]
public async Task<IActionResult> GetScreenshot(int id)
{
var invoice = await _invoices.GetByIdAsync(id);
var image = await _pagebolt.ScreenshotAsync($"https://yourapp.com/invoices/{id}");
return File(image, "image/png", $"invoice-{id}.png");
}
}
Azure Functions (Consumption Plan)
여기서는 브라우저 없이 접근하는 방법이 빛을 발합니다. Azure Functions Consumption 플랜에서는 Chromium 바이너리 다운로드를 위한 쓰기 가능한 디렉터리가 없기 때문에 PuppeteerSharp와 Playwright가 실패합니다. HTTP 호출은 정상적으로 작동합니다:
[Function("GenerateInvoicePdf")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "invoices/{id}/pdf")] HttpRequestData req,
int id)
{
var html = await _renderer.RenderAsync("Invoice", id);
var pdf = await _pagebolt.PdfFromHtmlAsync(html);
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
response.Headers.Add("Content-Disposition", $"attachment; filename=\"invoice-{id}.pdf\"");
await response.WriteBytesAsync(pdf);
return response;
}
Author
모든 코드 스니펫은 .NET 프로젝트에 바로 삽입할 수 있습니다. 외부 브라우저가 필요 없습니다.
브라우저 바이너리 없음. 파일 시스템 쓰기 없음. Consumption 플랜에서 작동합니다.
