2012-10-26 3 views
8

C# 웹 응용 프로그램에서 호출하는 wkhtmltopdf.exe를 사용하여 HTML 문서를 PDF로 렌더링하려고합니다.WkHtmlToPDF - stdin 및 머리글/바닥 글 작업

HTML 문서에는 각 페이지마다 반복되는 바닥 글과 머리글이 있어야합니다. 이는 --header-html <a path>을 인수로 지정하여 wkhtmltopdf에서 가능합니다.

그러나 바닥 글은 면도기 뷰에서 동적으로 렌더링되므로 디스크의 임시 파일에 저장하고 해당 경로를 사용하지 않아도되지만 이미 메모리에있는 렌더링 된 HTML을 사용하려고합니다. 즉, 문서 자체에 대한, 그래서처럼 StandardInput 스트림에 작성하여 가능 :

var wkhtml = ConfigurationManager.AppSettings["WkHtmlToPdfPath"]; 
var p = new Process(); 

p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
p.StartInfo.FileName = wkhtml; 

p.StartInfo.Arguments = "-q -n --disable-smart-shrinking - -"; 
p.Start(); 

var stdin = p.StandardInput; 
stdin.AutoFlush = true; 
stdin.Write(template); 
stdin.Dispose(); 

즉에 의존하지 않고 인라인을 통과, 머리글과 바닥 글 HTML에 대해 같은 일을 할 수 있나요 임시 파일? 내가 해봤

:

stdin.Write(string.Format("--footer-html {0} ", footer)); 

그러나 물론, 그냥 처리하는 문서가 아닌 바닥 글의 일부.

내가 꼬리말과 헤더를 동적으로 렌더링하려는 주된 이유는 (대부분) 다른 문제로 인한 것입니다. 동적 인 머리말과 꼬리말을 갖는 것이 좋겠지 만, 상대 경로 (예 : C : \ templates \ images \ logo.png)는 절대 경로로 이미지에 링크해야하는 문제를 해결하는 것이 대부분입니다. images/logo.png)는 stdin을 사용하고 HTML의 문자열 블롭을 전달할 때 작동하지 않으므로 런타임시 Razor를 통해 절대 경로를 삽입해야합니다. 이 문제에 대한

, 나는 상대 경로를 일치하는 프로세스의 작업 디렉토리 설정을 시도했지만, 아무 소용이 : 그 문제를 해결할 수 있다면

p.StartInfo.WorkingDirectory = @"C:\templates"; 

, 즉 90 %를 해결하는 것 문제도.

+2

Wkhtmltopdf 위협 헤더/푸터가 외부 경로/URL을 통해 분리되어 있기 때문에 나는 동적 인 데이터를 URL에 넣은 html 문서를 정의했다.그런 다음 일부 자바 스크립트로 추출했습니다. – Alex

답변

3

이 JulianR을 해결했는지 확인하고 MVC (?)에있는 것으로 가정합니다. 아래의 초기 코드 중 일부를 무시할 수는 있지만 출력을 직접 스트리밍해야하는 유사한 상황이있었습니다 사이트의 보안 섹션 및 로그인 섹션으로 인해 wkhtmltopdf.

첫째 컨트롤러에 당신은 당신이 (자체 머리글과 바닥 글을 사용할 수 있음) 적용 가능한 마스터 페이지와 디스플레이에 필요한보기에 뽑을 수 :

var view = ViewEngines.Engines.FindView(ControllerContext, myViewName, myMasterPageLayout); 

당신이 다음에이보기의 전류를 얻을 수 등 필요한을 ViewData, Tempdata하고, 문자열이 저장 (아래 내용) : 필요한 경우

string content; 
ViewData.Model = model; 
using (var writer = new System.IO.StringWriter()) 
{ 
    var context = new ViewContext(ControllerContext, view.View, ViewData, TempData, writer); 
    view.View.Render(context, writer); 
    writer.Flush(); 
    content = writer.ToString(); 
    writer.Close(); 
} 

이 단계에서 당신은 실제로 문자열에 출력되는 HTML을 수정할 수 - 예를 전체 경로 당신과 함께

출력 HTML 당신은 그럼 그냥 wkhtmltopdf에 전달하는 로컬 경로를 변경하려면 :

var p = new Process(); 
p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
//Other parameters as required 
byte[] file; 
try 
{ 
    p.Start(); 
    byte[] buffer = new byte[32768]; 

    using (System.IO.StreamWriter stdin = p.StandardInput) 
    { 
     stdin.AutoFlush = true; 
     stdin.Write(content); 
    } 


    using (MemoryStream ms = new MemoryStream()) 
    { 
     ms.Position = 0; 
     p.StandardOutput.BaseStream.CopyTo(ms); 
     file = ms.ToArray(); 
    } 

    p.StandardOutput.Close(); 
    // wait or exit 
    p.WaitForExit(60000); 

    // read the exit code, close process 
    int returnCode = p.ExitCode; 

} 

그런 다음 전체 페이지의 당신의 PDF 콘텐츠가 포함 된 바이트 배열을 가지고있다.

+0

정보 주셔서 감사합니다. 필자는이 문제를 해결하지 않고 보고서를 편집 할 때 상당한 불만에도 불구하고 여러 가지 장점 (단순함, 기본 인쇄 지원)을 갖춘 Microsoft RDLC 보고서를 사용했습니다. – JulianR