2015-01-20 8 views
5

Ich versuche, eine Web-API zu erstellen, die eine formatierte HTML-Datei in eine PDF konvertieren kann.Hanging Dienstag nach der ersten Konvertierung

Ich benutze DienstagPechkin und habe meine Anwendung in IIS installiert (als 32-Bit-App: Ich habe den Anwendungspool geändert, um im 32-Bit-Modus zu laufen).

IIS 8.5 läuft unter Windows Server 2012 R2.

PDFConversion Klasse in C#:

using System.Drawing.Printing; 
using System.IO; 
using TuesPechkin; 

namespace PDFApi 
{ 
    public class PDFcreator 
    { 
     public void convert(string path, string uri) 
     { 
      IConverter converter = new StandardConverter(
       new RemotingToolset<PdfToolset>(
        new Win64EmbeddedDeployment(
        new TempFolderDelpoyment()))); 

      var document = new HtmlToPdfDocument 
      { 
       GlobalSettings = 
       { 
        ProduceOutline = true, 
        DocumentTitle = "Converted Form", 
        PaperSize = PaperKind.A4, 
        Margins = 
        { 
         All = 1.375, 
         Unit = Unit.Centimeters 
        } 
       }, 
       Objects = 
       { 
        new ObjectSettings { RawData = File.ReadAllBytes(uri) } 
       } 
      }; 

      byte[] pdfBuf = converter.Convert(document); 

      FileStream fs = new FileStream(path, FileMode.Create); 
      fs.Write(pdfBuf, 0, pdfBuf.Length); 
      fs.Close(); 
     } 
    } 
} 

Der Regler ist wie folgt:

[Route("converthtml")] 
    [HttpPost] 
    [MIMEContentFilter] 
    public async Task<HttpResponseMessage> ConvertHtml() 
    { 
     string temppath = System.IO.Path.GetTempPath(); 

     var streamProvider = new MultipartFormDataStreamProvider(temppath); 
     await Request.Content.ReadAsMultipartAsync(streamProvider); 


     string filepath = streamProvider.FileData.Select(entry => entry.LocalFileName.Replace(temppath + "\\", "")).First<string>(); 
     string pdfpath = System.IO.Path.GetTempFileName(); 
     pdfpath = pdfpath.Substring(0, pdfpath.LastIndexOf('.')) + ".pdf"; 

     new PDFcreator().convert(pdfpath, filepath); 

     var stream = new FileStream(pdfpath, FileMode.Open); 
     var result = new HttpResponseMessage(HttpStatusCode.OK); 
     result.Content = new StreamContent(stream); 
     result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 
     return result; 
    } 

Hier ist, wo es ein wenig seltsam bekommt: Das Experimentieren in Fiedler, sobald das Senden einer Datei kehrt das PDF sofort . Alle nachfolgenden POSTs lassen jedoch Fiddler hängen. Examining Task Manager zeigt die CPU und Arbeitsspeicher für diese Aufgabe auf 13,5% und ~ 96 MB springen.

Der Temp-Ordner (in dem die Dateien gespeichert sind) enthält bei erfolgreicher Ausführung drei Dateien: die ursprüngliche hochgeladene Datei (mit einem GUID-ähnlichen Namen gespeichert), die über wkHtmlToPdf erzeugte Datei (im Formular) "wktemp-") und das generierte PDF (als tempXXXX.pdf). Wenn es hängt, kann nur die erste Datei gefunden werden, was anzeigt, dass das Problem irgendwo in wkHtmlToPdf selbst liegt.

Der eigentliche Kicker ist jedoch, wenn der Prozess im Task-Manager manuell beendet wird, die API erfolgreich abgeschlossen, gibt das PDF, vollständig erstellt zurück!

Wenn IIS zurückgesetzt wird, kehrt der Prozess in den ursprünglichen Zustand zurück; ein neuer Versuch wird ohne Problem funktionieren.

Offensichtlich IIS nach jedem Gespräch Zurücksetzen ist kaum durchführbar, noch von Hand ist der Prozess jedes Mal zu töten ...

Ist das ein Bug/Gibt es Lösungen für dieses Problem?

+1

Sieht aus wie Sie mit 'StandardConverter' statt' ThreadSafeConverter' . – tuespetre

+0

Ja, das hat mein Problem gelöst, danke! Ich habe den Konverter auch aus der Funktion entfernt und statisch gemacht. –

Antwort

0

Es scheint, Sie verwenden WkHtmlToPdf 64 Bit und Sie haben die 32 Bit installiert.

sollten Sie ändern:

 IConverter converter = new StandardConverter(
      new RemotingToolset<PdfToolset>(
       new Win64EmbeddedDeployment(
       new TempFolderDelpoyment()))); 

zu

 IConverter converter = new StandardConverter(
      new RemotingToolset<PdfToolset>(
       new Win32EmbeddedDeployment(
       new TempFolderDelpoyment()))); 
4
  var tempFolderDeployment = new TempFolderDeployment(); 
      var win32EmbeddedDeployment = new Win32EmbeddedDeployment(TempFolderDeployment); 
      var remotingToolset = new RemotingToolset<PdfToolset>(Win32EmbeddedDeployment); 

      var converter = 
       new ThreadSafeConverter(RemotingToolset); 


      byte[] pdfBuf = converter.Convert(document); 
      remotingToolset.Unload(); 

Unload remotingToolset verhindern hängen RemotingToolset.Unload();

+1

Dies ist für mich gelöst (mit 64-Bit-Bereitstellung). Der Konverter sollte eine Option haben, um dies weiterzugeben. Aber akzeptabel. Vielen Dank! – TravisWhidden

+0

Dies funktionierte für mich auch mit WinAnyCPUEmbeddedDeployment. – noCodeMonkeys