refactoring Pdf generation

This commit is contained in:
2016-11-30 11:01:22 +01:00
parent 1d69a7ea74
commit 0582421523
3 changed files with 102 additions and 80 deletions

View File

@ -79,13 +79,13 @@ namespace Yavsc.ApiControllers
public IActionResult GetTex(long id) public IActionResult GetTex(long id)
{ {
Response.ContentType = "text/x-tex"; Response.ContentType = "text/x-tex";
return ViewComponent("Estimate",new object[] { id, false }); return ViewComponent("Estimate",new object[] { id, "LaTeX" });
} }
[HttpPost("gen/{id}")] [HttpPost("gen/{id}")]
public IActionResult GeneratePdf(long id) public IActionResult GeneratePdf(long id)
{ {
return ViewComponent("Estimate",new object[] { id, true } ); return ViewComponent("Estimate",new object[] { id, "Pdf" } );
} }
} }
} }

View File

@ -1,29 +1,34 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines; using Microsoft.AspNet.Mvc.ViewEngines;
using Yavsc.ViewModels.Gen;
namespace Yavsc.Helpers namespace Yavsc.Helpers
{ {
public class TeXString { public class TeXString
{
public class Replacement { public class Replacement
{
string target; string target;
string replacement; string replacement;
public Replacement(string target, string replacement){ public Replacement(string target, string replacement)
this.target=target; {
this.replacement=replacement; this.target = target;
this.replacement = replacement;
} }
public string Execute(string source) public string Execute(string source)
{ {
return source.Replace(target,replacement); return source.Replace(target, replacement);
} }
} }
public readonly static Replacement[] SpecialCharsRendering = public readonly static Replacement[] SpecialCharsRendering =
{ {
new Replacement("<","\\textless"), new Replacement("<","\\textless"),
new Replacement(">","\\textgreater"), new Replacement(">","\\textgreater"),
@ -49,13 +54,15 @@ namespace Yavsc.Helpers
new Replacement("","\\textendash") new Replacement("","\\textendash")
}; };
string data; string data;
public TeXString(string str) { public TeXString(string str)
{
data = str; data = str;
foreach (var r in SpecialCharsRendering) { foreach (var r in SpecialCharsRendering)
{
data = r.Execute(data); data = r.Execute(data);
} }
} }
override public string ToString() override public string ToString()
{ {
return data; return data;
@ -64,45 +71,88 @@ namespace Yavsc.Helpers
public static class TeXHelpers public static class TeXHelpers
{ {
public static string NewLinesWith(this string target, string separator) public static string NewLinesWith(this string target, string separator)
{ {
var items = target.Split(new char[] {'\n'}).Where( var items = target.Split(new char[] { '\n' }).Where(
s=> !string.IsNullOrWhiteSpace(s) ) ; s => !string.IsNullOrWhiteSpace(s));
return string.Join(separator, items); return string.Join(separator, items);
} }
public static TeXString ToTeX(string target, string lineSeparator="\n\\\\") public static TeXString ToTeX(string target, string lineSeparator = "\n\\\\")
{ {
if (target==null) return null; if (target == null) return null;
return new TeXString(target.NewLinesWith(lineSeparator)); return new TeXString(target.NewLinesWith(lineSeparator));
} }
public static bool GenerateEstimatePdf(this PdfGenerationViewModel Model)
{
string errorMsg = null;
var billdir = Model.DestDir;
var tempdir = Startup.SiteSetup.TempDir;
string name = Model.BaseFileName;
string fullname = new FileInfo(
System.IO.Path.Combine(tempdir, name)).FullName;
string ofullname = new FileInfo(
System.IO.Path.Combine(billdir, name)).FullName;
FileInfo fi = new FileInfo(fullname + ".tex");
FileInfo fo = new FileInfo(ofullname + ".pdf");
using (StreamWriter sw = new StreamWriter(fi.FullName))
{
sw.Write(Model.TeXSource);
}
if (!fi.Exists)
{
errorMsg = "Source write failed";
}
else
{
using (Process p = new Process())
{
p.StartInfo.WorkingDirectory = tempdir;
p.StartInfo = new ProcessStartInfo();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "/usr/bin/texi2pdf";
p.StartInfo.Arguments = $"--batch --build-dir=. -o {fo.FullName} {fi.FullName}";
p.Start();
p.WaitForExit();
if (p.ExitCode != 0)
{
errorMsg = $"Pdf generation failed with exit code: {p.ExitCode}";
}
}
fi.Delete();
}
Model.Generated = fo.Exists;
Model.GenerationErrorMessage = new HtmlString(errorMsg);
return fo.Exists;
}
public static string RenderViewToString( public static string RenderViewToString(
this Controller controller, IViewEngine engine, this Controller controller, IViewEngine engine,
IHttpContextAccessor httpContextAccessor, IHttpContextAccessor httpContextAccessor,
string viewName, object model) string viewName, object model)
{ {
using (var sw = new StringWriter()) using (var sw = new StringWriter())
{ {
if (engine == null) if (engine == null)
throw new InvalidOperationException("no engine"); throw new InvalidOperationException("no engine");
// try to find the specified view // try to find the specified view
controller.TryValidateModel(model); controller.TryValidateModel(model);
ViewEngineResult viewResult = engine.FindPartialView(controller.ActionContext, viewName); ViewEngineResult viewResult = engine.FindPartialView(controller.ActionContext, viewName);
// create the associated context // create the associated context
ViewContext viewContext = new ViewContext(); ViewContext viewContext = new ViewContext();
viewContext.ActionDescriptor = controller.ActionContext.ActionDescriptor; viewContext.ActionDescriptor = controller.ActionContext.ActionDescriptor;
viewContext.HttpContext = controller.ActionContext.HttpContext; viewContext.HttpContext = controller.ActionContext.HttpContext;
viewContext.TempData = controller.TempData; viewContext.TempData = controller.TempData;
viewContext.View = viewResult.View; viewContext.View = viewResult.View;
viewContext.Writer = sw; viewContext.Writer = sw;
// write the render view with the given context to the stringwriter // write the render view with the given context to the stringwriter
viewResult.View.RenderAsync(viewContext); viewResult.View.RenderAsync(viewContext);
viewResult.EnsureSuccessful(); viewResult.EnsureSuccessful();
return sw.GetStringBuilder().ToString(); return sw.GetStringBuilder().ToString();
} }
} }
} }
} }

View File

@ -4,47 +4,19 @@
@using System.Diagnostics @using System.Diagnostics
@using System.Text @using System.Text
@using Yavsc.Formatters @using Yavsc.Formatters
@using Yavsc.Helpers
@model Yavsc.ViewModels.Gen.PdfGenerationViewModel @model Yavsc.ViewModels.Gen.PdfGenerationViewModel
@{
string errorMsg = null;
var billdir = Model.DestDir;
var tempdir = Startup.SiteSetup.TempDir;
string name = Model.BaseFileName;
string fullname = new FileInfo(
System.IO.Path.Combine(tempdir,name)).FullName;
string ofullname = new FileInfo(
System.IO.Path.Combine(billdir,name)).FullName;
FileInfo fi = new FileInfo(fullname + ".tex"); @{
FileInfo fo = new FileInfo(ofullname + ".pdf"); Model.GenerateEstimatePdf();
using (StreamWriter sw = new StreamWriter (fi.FullName))
{
sw.Write (Model.TeXSource);
}
if (!fi.Exists)
{
errorMsg = "Source write failed";
}
else {
using (Process p = new Process ()) {
p.StartInfo.WorkingDirectory = tempdir;
p.StartInfo = new ProcessStartInfo ();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "/usr/bin/texi2pdf";
p.StartInfo.Arguments = $"--batch --build-dir=. -o {fo.FullName} {fi.FullName}";
p.Start ();
p.WaitForExit ();
if (p.ExitCode != 0) {
errorMsg = $"Pdf generation failed with exit code: {p.ExitCode}";
}
}
fi.Delete();
}
ViewBag.GenSuccess = fo.Exists;
} }
@if (ViewBag.GenSuccess) { @if (Model.Generated) {
@($"{name}.pdf") <div>
@(Model.BaseFileName).pdf was generated
</div>
} else { } else {
@errorMsg <div class="error">
<text>Something went wrong ...</text> @Model.GenerationErrorMessage
<p>Something went wrong ...</p>
</div>
} }