前回に引き続き、iTextSharpですが、PDFテンプレートを作っておいて出力したい時があると思います。
メソッド引数が変わって、ちょっとハマったところがあったので、書いてみたいと思います。
PDFテンプレートを配置する
pdfをプロジェクト配下の適当な位置に配置します。
今回もプロジェクトから使うので、右クリックして常にコピーにしておきます。
ソース
functionのところを載せてます!詳細はgithubを見てください。
[FunctionName("TestPdfOutputOverwrite")]
public HttpResponseMessage TestPdfOutputOverwrite(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "test_output_pdf")] HttpRequest req,
ILogger log
)
{
EncodingProvider encodingProvider;
encodingProvider = CodePagesEncodingProvider.Instance;
Encoding.RegisterProvider(encodingProvider);
// 取得したPDFのサイズでDocument作成
var reader = new PdfReader(@"Google.pdf");
var doc = new Document(reader.GetPageSize(1));
var ms = new MemoryStream();
//ファイルの出力先を設定
var pw = PdfWriter.GetInstance(doc, ms);
//ドキュメントを開く
doc.Open();
var pdfContentByte = pw.DirectContent;
// テンプレートのページを追加する
doc.NewPage();
var page = pw.GetImportedPage(reader, 1);
pdfContentByte.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
var bf = BaseFont.CreateFont(@"MS Gothic.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// ベースフォントとフォントサイズを指定する。
pdfContentByte.SetFontAndSize(bf, 10);
// 指定箇所に文字列を記述
ShowTextAligned(pdfContentByte, 10, 500, "Googleのページやで!");
ShowTextAligned(pdfContentByte, 10, 480, "日本語の出力テスト。");
DrawLine(pdfContentByte, 2, 451, 840, 451);
doc.Close();
// レスポンス作成
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(ms.GetBuffer())
};
//Content-Dispositionをattachmentでファイル名を指定していたらプレビューが開かない
//response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
//{
// FileName = "testhoge.pdf"
//};
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
return response;
}
説明
PDFをテンプレートにするときに注意する点ですが、下記のようにPdfReaderで対象ファイルを読み込んで、
var reader = new PdfReader(@"Google.pdf");
PdfContentByteにページとして追加します。これを編集して行って、最後に出力しています。
doc.NewPage();
var page = pw.GetImportedPage(reader, 1);
pdfContentByte.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
後はほとんど前回と同じですね。
AddTemplateのパラメータの数が分からなかったので、ハマりました。調べても三つだけのやつが多い😖
バージョンが新しくなったんでしょうねー。
動作確認
下記のように作成したPDFを読み込んで、文字を乗せることができました!
Azureでリソースがなくて動かない
ローカルで動かすとしっかり動作しましたが、
Azure上でfunctionを動かすと、pdfとフォントがない旨のエラーが出て動作しませんでした。
githubのソースは変更しています。
下記のように修正するとAzureでも動くようになります。
pdfとfontのリソースを右クリックして、埋め込みリソースにします。(embedded resourceを選択)
下記のようにテンプレートとフォントを取得します。
// リソース取得
Assembly assembly = Assembly.GetExecutingAssembly();
Stream pdfStream = assembly.GetManifestResourceStream("iTextSharpFunction.Google.pdf");
Stream fontStream = assembly.GetManifestResourceStream("iTextSharpFunction.MS Gothic.ttf");
ストリームをPdfReaderに渡して使います。
var reader = new PdfReader(pdfStream);
CreateFontは引数を増やして、下記のようにすると渡せました。
var bf = BaseFont.CreateFont(@"MS Gothic.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, GetStreamToBytes(fontStream), null);
streamからbyte配列に変えないと、メソッドに渡せなかったので下記のようなprivateメソッドを用意しました。
private static byte[] GetStreamToBytes(Stream input)
{
byte[] buffer = new byte[input.Length * 2];
var ms = new MemoryStream();
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
githubにソースを…
今回も置いてます!(同じプロジェクトでfunctionを分けてます。)
コメント