4

MVC3とRazorビューエンジンを使用してWebサイトを作成しました。私がやりたいのは、結果のHTMLを取得してストリームまたは文字列に格納し、ブラウザーに書き込む代わりにファイルに書き込むことができるようにすることです。

私がする必要があるのは、結果のHTMLを取得してPDFに変換し、レポートの形式としてPDFをユーザーに提供することです。私はそれのその部分をすでに解決しました、私はHTMLをある種の変数に取り込むための最良の方法を理解することができません。

編集-私は少し違う方向に進んでしまい、結果を共有したいと思いました。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);
    }
}
4

2 に答える 2

5

私はこのコードを使用します:

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();
}

これは現在のControllerContext;を使用します。それを望まない場合は、をモックする必要がありますHttpContextBase

TempDataビューからデータを戻したい場合は、ではなく、でデータを渡す必要がありますViewBag

于 2011-02-28T21:45:13.253 に答える
0

@http ://razorengine.codeplex.com/をご覧ください

于 2011-02-28T21:56:07.840 に答える