2011-02-28 2 views
4

면도기 뷰 엔진과 함께 MVC3을 사용하여 웹 사이트를 만들었습니다. 내가하고 싶은 것은 결과 HTML을 가져 와서 스트림이나 문자열에 저장하여 브라우저에 쓰는 대신 파일에 쓸 수 있도록하는 것입니다.면도기 뷰 엔진을 사용하여 브라우저에 쓰는 대신 결과 HTML을 문자열로 저장하려면 어떻게해야합니까?

결과 HTML을 가져 와서 PDF로 변환하고 PDF를보고 양식으로 제공하십시오. 나는 그 부분을 이미 해결했지만, HTML을 일종의 변수로 가져 오는 최선의 방법을 찾지 못했습니다.

EDIT - 조금 다른 방향으로 가고 결국 결과를 공유하고 싶습니다. WKHTMLTOPDF 프로젝트를 사용하여 스트림을 PDF로 변환하는 특성을 만들었습니다. 이제는 액션에 속성을 추가하고 브라우저에 HTML을 렌더링하는 대신 대화 상자로 저장을 팝업합니다.

public class PdfInterceptAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     var viewResult = filterContext.Result as ViewResult; 
     var workingDir = ConfigurationManager.AppSettings["PdfWorkingPath"]; 
     var fileName = workingDir + @"\" + Guid.NewGuid() + ".pdf"; 

     if (viewResult != null) 
     { 
      var view = viewResult.View; 
      var writer = new StringWriter(); 
      var viewContext = new ViewContext(filterContext.Controller.ControllerContext, view, 
       viewResult.ViewData, viewResult.TempData, writer); 
      view.Render(viewContext, writer); 
      HtmlToPdf(new StringBuilder(writer.ToString()), fileName); 
      filterContext.HttpContext.Response.Clear(); 
      var pdfByte = File.ReadAllBytes(fileName); 
      filterContext.HttpContext.Response.ContentType = "application/pdf"; 
      filterContext.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf"); 
      filterContext.HttpContext.Response.BinaryWrite(pdfByte); 
      filterContext.HttpContext.Response.End(); 
     } 

     base.OnResultExecuted(filterContext); 
    } 

    private static bool HtmlToPdf(StringBuilder file, string fileName) 
    { 
     // assemble destination PDF file name 

     var workingDir = ConfigurationManager.AppSettings["PdfWorkingPath"]; 
     var exePath = ConfigurationManager.AppSettings["PdfExePath"]; //Path to the WKHTMLTOPDF executable. 
     var p = new Process 
        { 
         StartInfo = {FileName = @"""" + exePath + @""""} 
        }; 

     var switches = "--print-media-type "; 
     switches += "--margin-top 4mm --margin-bottom 4mm --margin-right 0mm --margin-left 0mm "; 
     switches += "--page-size A4 "; 

     p.StartInfo.Arguments = switches + " " + "-" + " " + fileName; 

     p.StartInfo.UseShellExecute = false; // needs to be false in order to redirect output 
     p.StartInfo.RedirectStandardOutput = true; 
     //p.StartInfo.RedirectStandardError = true; 
     p.StartInfo.RedirectStandardInput = true; // redirect all 3, as it should be all 3 or none 
     p.StartInfo.WorkingDirectory = workingDir; 

     p.Start(); 
     var sw = p.StandardInput; 
     sw.Write(file.ToString()); 
     sw.Close(); 

     // read the output here... 
     string output = p.StandardOutput.ReadToEnd(); 

     // ...then wait n milliseconds for exit (as after exit, it can't read the output) 
     p.WaitForExit(60000); 

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

     // if 0 or 2, it worked (not sure about other values, I want a better way to confirm this) 
     return (returnCode <= 2); 
    } 
} 

답변

5

는이 코드 사용이 현재 ControllerContext 사용

private string RenderView<TModel>(string viewPath, TModel model, TempDataDictionary tempData = null) { 
    var view = new RazorView(
     ControllerContext, 
     viewPath: viewPath, 
     layoutPath: null, 
     runViewStartPages: false, 
     viewStartFileExtensions: null 
    ); 

    var writer = new StringWriter(); 
    var viewContext = new ViewContext(ControllerContext, view, new ViewDataDictionary<TModel>(model), tempData ?? new TempDataDictionary(), writer); 
    view.Render(viewContext, writer); 
    return writer.ToString(); 
} 

을; 원하지 않으면 HttpContextBase을 조롱해야합니다.

보기에서 데이터를 다시 전달하려면 ViewBag이 아닌 TempData으로 전달해야합니다.

+0

viewPath 인수를 지정하는 쉬운 방법이 있습니까? – Dean

+0

@Dean : 무슨 소리 야? 아마도 당신은'BuildManagerViewEngine'에서 코드를 찾고있을 것입니다 (MVC 소스를보세요) – SLaks

관련 문제