I have the following code:
[Authorize]
[HttpGet]
public FileContentResult DownloadMsgAsPdf(string FileId, string outer = "")
{
var Results = (SearchResult)TempData["Results"];
var msg = Results.emails[FileId];
...
return File(pdfBytes, System.Net.Mime.MediaTypeNames.Application.Octet, msg.Id + ".pdf");
}
Now upon running it once (clicking a link) it does everything completely fine. However upon clicking it a second time (with nothing else changed or called) it errors out, with Results being null. I assume this means TempData is getting cleared, but how could this be?
Here is the full code if it's needed:
[Authorize]
[HttpGet]
public FileContentResult DownloadMsgAsPdf(string FileId, string outer = "")
{
var Results = (SearchResult)TempData["Results"];
var msg = Results.emails[FileId];
TempData.Keep();
msg.BodyHTML = System.Web.HttpUtility.HtmlDecode(msg.BodyHTML);
var htmlContent = String.Format("<center><p><b>Case ID</b>: " + msg.Id
+ " <b>User ID</b>: " + Session["userid"]
+ " <b>Privileged</b>: ");
if (msg.Tags != null)
{
htmlContent += msg.Tags.ContainsKey("privileged");
}
else
{
htmlContent += "False";
}
htmlContent += " <b>Downloaded</b>: " + DateTime.Now.ToString("g") + "</center>"
+ " <p> -- Forwarded message -- </p> "
+ " <p><b> From :</b> <a href='#'>" + msg.From + "</a> </p> "
+ " <p><b> Date:</b> Mon, oct 25 2010 at 4:42 PM </p> "
+ " <p> <b>Subject:</b> " + msg.Subject + " </p> "
+ " <p><b> To:</b> " + msg.To + " </p> "
+ " <p><b> Cc: </b> </p> "
+ " <div> "
+ " <ul> ";
if(msg.attachementList != null){
if (!msg.attachementList.Any())
{
htmlContent += "<text> "
+ "<li><label style='color:gray'>No attachment</label></li></text>";
}
else
{
foreach (var attachment in msg.attachementList)
{
var filename = System.IO.Path.GetFileName(attachment);
htmlContent += "<text> "
+ "<li><a href='#'>" + filename + "</a></li></text>";
}
}
}
htmlContent += "</ul>"
+ "</div>"
+ "<div padding: 5px;'>"
+ msg.BodyText
+ "</div>"
+ "</div>";
var pdfBytes = (new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(htmlContent);
if (outer != "")
{
return File(pdfBytes, System.Net.Mime.MediaTypeNames.Application.Octet, msg.Id + ".pdf");
}
return new FileContentResult(pdfBytes, "application/pdf");
}
TempData means you only can get once. And i see you use TempData.Keep(), but this method only effect on the same http context. I think you can use Session or Cache instead of the TempData.
Related
Hello I have a model method that looks like this.
public string menuItems(bool drop)
{
var baseUrl = IGT.baseUrl;// string.Format("{0}://{1}{2}", HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Authority, HttpRuntime.AppDomainAppVirtualPath);
string addmore = "<a class='dropdown-item' href=" + baseUrl + "DODetails/Create?orderID=" + ID.ToString() + ">Add More</a>";
string changestatus = "<a class='dropdown-item' href=" + baseUrl + "DisposalOrders/ChangeStatus/" + ID.ToString() + ">Change Status</a>";
string details = "<a class='dropdown-item' href=" + baseUrl + "DisposalOrders/Details?id=" + ID.ToString() + ">Details</a>";
string delete = "<a class='dropdown-item' href=" + baseUrl + "DisposalOrders/Delete?id=" + ID.ToString() + ">Delete</a>";
string edit = "<a class='dropdown-item' href=" + baseUrl + "DisposalOrders/Edit?id=" + ID.ToString() + ">Edit</a>";
string notes = "<a class='dropdown-item' href=" + baseUrl + "DisposalOrders/Notes/" + ID.ToString() + ">Notes</a>";
//string delim = " | ";
switch (Status)
{
case DOStatus.Pending:
return addmore + " | " + edit + " | " + details + " | " + changestatus + " | " + delete + " | " + notes;
//return String.Concat(addmore, delim, changestatus, delim, delete, delim, details, delim, edit, delim, notes);
case DOStatus.Disposed:
return details + notes;
};
return details;
}
And a view page that returns those values by doing this
<p>
#Html.Raw(Model.menuItems(false)) | #Html.ActionLink("Back to List", "Index")
</p>
I have done this with other pages in my site and it looks like this
But what mine currently does is
I don't know if it's a system bug or something wrong with my code or what. Just confused at what the issue is right now
Here is my Markup
First, I apologize for the length of this, but it's all I knew when I started. Now I'm experimenting with the foreach, List<t> and TreeView classes to avoid repetition as recmomended by SO community.
The form will collect information via text boxes, allow attachments of files with file dialogs and collate all info into a neat HTML bodied email. We sell slabs.. and my original code looked a little like this:
private void PrepareReturnEmailTwoSlabs()
{
LoadSettings();
string Fname = Properties.Settings.Default.FabricatorName;
string Facc = Properties.Settings.Default.FabricatorAccountNo;
string Fadd1 = Properties.Settings.Default.FabricatorAddress1;
string Fadd2 = Properties.Settings.Default.FabricatorAddress2;
string Ftown = Properties.Settings.Default.FabricatorTown;
string Fcounty = Properties.Settings.Default.FabricatorCounty;
string Fpostcode = Properties.Settings.Default.FabricatorPostcode;
string Fphoneno = Properties.Settings.Default.FabricatorPhone;
string Femail = Properties.Settings.Default.FabricatorEmail;
string Fclient = Properties.Settings.Default.ClientManagerEmail;
string Fcentre = Properties.Settings.Default.CentreEmail;
string FQt = Properties.Settings.Default.QTEmail;
string Dateofinv = dateTimePicker1.Value.ToShortDateString();
string Inv = textBox13.Text;
string Material1 = textBox14.Text;
string Thick1 = comboBox8.SelectedValue.ToString();
string Batch1 = textBox44.Text;
string Reason1 = comboBox1.SelectedValue.ToString();
string Notes = textBox18.Text;
string Thick2 = comboBox7.SelectedValue.ToString();
string Material2 = textBox15.Text;
string Batch2 = textBox45.Text;
string Reason2 = comboBox2.SelectedValue.ToString();
if (Thick2 == null)
{
Thick2 = "not selected";
}
if (Material2 == null)
{
Material2 = "not selected ";
}
if (Batch2 == null)
{
Batch2 = "not selected ";
}
if (Reason2 == null)
{
Reason2 = "not selected ";
}
GenerateUniqueRefReturn();
//construct email
var message = new MimeMessage();
message.From.Add(new MailboxAddress("************", "***************"));
message.To.Add(new MailboxAddress("**********", "********"));
message.Subject = "Return" + " " + Returnid;
//different message bodies dependant on how many slabs are chosen
TextPart body2 = new TextPart("html")
{
Text = #"Please See Below Information" + "<br/>" +
"<h4>Return ID: " + " " + Returnid + "</h4>" + "<br/>" +
"<b>Fabricator Name:</b>" + " " + Fname + "<br/>" + Environment.NewLine +
"<b>Account Number:</b>" + " " + Facc + "<br/>" + Environment.NewLine +
"<b>Address Line 1:</b>" + " " + Fadd1 + "<br/>" + Environment.NewLine +
"<b>Address Line 2:</b>" + " " + Fadd2 + "<br/>" + Environment.NewLine +
"<b>Town:</b>" + " " + Ftown + "<br/> " + Environment.NewLine +
"<b>County:</b>" + " " + Fcounty + "<br/>" + Environment.NewLine +
"<b>Postcode:</b>" + " " + Fpostcode + "<br/>" + Environment.NewLine +
"<b>Phone:</b>" + " " + Fphoneno + "<br/>" + Environment.NewLine +
"<b>Email:</b>" + " " + Femail + "<br/>" + Environment.NewLine + "<br/>" +
"<br/>" +
"<b>Date Of Invoice: </b>" + " " + DoI + "<br/>" +
"<b>Invoice: </b>" + " " + Inv + "<br/>" +
"<b>Material Information:</b>" + "<br/>" +
//slab 1
"<b>Thickness: </b>" + " " + Thick1 + "mm" + "<br/>" +
"<b>Material Name: </b>" + " " + Material1 + "<br/>" +
"<b>Batch No: </b>" + " " + Batch1 + "<br/>" +
"<b>Reason for Return: </b>" + " " + Reason1 + "<br/>" + "<br/>" +
//slab 2
"<b>Thickness: </b>" + " " + Thick2 + "mm" + "<br/>" +
"<b>Material Name: </b>" + " " + Material2 + "<br/>" +
"<b>Batch No: </b>" + " " + Batch2 + "<br/>" +
"<b>Reason for Return: </b>" + " " + Reason2 + "<br/>" + "<br/>" +
"<br/>" +
"<b>Notes:" + " " + Notes
};
var builder = new BodyBuilder();
//check for return attachment and if found, assign attachment to message via bodybuilder
if (checkBox5.Checked)
{
builder.TextBody = body2.Text;
builder.HtmlBody = body2.Text;
builder.Attachments.Add(ReturnAttachment1);
message.Body = builder.ToMessageBody();
}
if (checkBox7.Checked)
{
builder.TextBody = body2.Text;
builder.HtmlBody = body2.Text;
builder.Attachments.Add(ReturnAttachment1);
builder.Attachments.Add(ReturnAttachment2);
message.Body = builder.ToMessageBody();
}
if (checkBox6.Checked)
{
builder.TextBody = body2.Text;
builder.HtmlBody = body2.Text;
builder.Attachments.Add(ReturnAttachment1);
builder.Attachments.Add(ReturnAttachment2);
builder.Attachments.Add(ReturnAttachment3);
message.Body = builder.ToMessageBody();
}
else
{
message.Body = body2;
}
//Connection to SMTP and Criteria to Send
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect("smtp.gmail.com", 587, false);
// Note: only needed if the SMTP server requires authentication
client.Authenticate("***************#********.com", "*********");
client.Send(message);
client.Disconnect(true);
This code was repeated all the way up to five slabs. So now, I have a class:
{
public string Thickness { get; set; }
public string Material { get; set; }
public string Batch { get; set; }
public Slab(string Thick, string Mat, string Batchno)
{
Thickness = Thick;
Material = Mat;
Batch = Batchno;
}
}
A List that holds this object:
private void button1_Click(object sender, EventArgs e)
{
string t = comboBox1.SelectedValue.ToString();
string m = comboBox2.SelectedValue.ToString();
string b = textBox6.Text;
Slab S = new Slab(t, m, b);
allSlabs.Add(S);
PaintTree();
}
public void PaintTree()
{
int ParentIndex;
TreeSlabs.Nodes.Clear();
foreach (Slab slab in allSlabs)
{
TreeSlabs.BeginUpdate();
TreeSlabs.Nodes.Add("Slab" + " " + (allSlabs.IndexOf(slab) + 1).ToString());
ParentIndex = allSlabs.IndexOf(slab);
TreeSlabs.Nodes[ParentIndex].Nodes.Add("Thickness: " + $"{slab.Thickness}");
TreeSlabs.Nodes[ParentIndex].Nodes.Add("Material: " + $"{slab.Material}");
TreeSlabs.Nodes[ParentIndex].Nodes.Add("Batch: " + $"{slab.Batch}");
TreeSlabs.EndUpdate();
}
}
Now i want to create a foreach.. that iterates through each node.. and collects the info from the parent and its children foreach node, and somehow instantiate new HTML methods for each node..
Foreach Node:
Compose HTML Line - new HTML
Slab 1:
Thickness:
Material
Batch
Slab 2:... etc
If theres 8 nodes, it generates 8 of those bodies. i can think of ways.. but i KNOW they're defintely not the correct ways to go about it based on what ive read and seen out there.
Many Thanks
You don't need to iterate through the tree and try to reclaim the data you put into it from the List of Slabs; it would be simpler to enumerate the List:
By the way, some other tips:
don't beginupdate/endupdate inside the loop, do it outside
the Add method that adds a node to a tree returns the node it added; you don't have to find it again by index, just capture it var justAdded = rootnode.Add("parent node"); and then add your thickness etc to it justAdded.Nodes.Add("thickness..."). The only add command that doesn't return the added mode is the one that takes a treenode type object; it doesn't need to return it because you already have it
consider adding a method to your slab to return some html, to simplify things
you can tidy all that html up with some string interpolation like you did with your $"{slab.thickness}" etc
i am trying to get the values of my controls like this:
function ConfirmWithUser()
{
var nodeText = '';
$('.mytreeview input[#type=checkbox]:checked').each(function() {
nodeText += $(this).next('a').text() + '\r';
});
var confirmationMessage;
confirmationMessage = "Please review the data before submitting:" + "\r"
+ "Sample Received Date: " + document.getElementById(received_dateTextbox).Value + "\r"
+ "Site of Ocurrence: " + document.getElementById(site_of_occurrenceTextBox).Value + "\r"
+ "Occurrence Date: " + document.getElementById(occurrence_dateTextBox).Value + "\r"
+ "Report Date: " + document.getElementById(report_byTextBox).Value + "\r"
+ "Specimen ID: " + document.getElementById(spec_idTextBox).Value + "\r"
+ "Batch ID: " + document.getElementById(batch_idTextBox).Value + "\r\n"
+ "Report Initiated By: " + document.getElementById(report_byTextBox).Value + "\r\n"
+ "Problem Identified By: " + $("input[#name=RadioButtonList1]:checked").val() + "\r\n"
+ "Problem List: " + nodeText;
HiddenFieldConfirmation.Value = confirmationMessage;
if (confirm(document.getElementById('HiddenFieldConfirmation').value) == true)
{ return true; }
else
{ return false; }
}
and the CONFIRM box is not firing at all! i do not get any pop up.
i tried to debug using firefox, and as soon as it go to this line:
confirmationMessage = "Please review the data before submitting:" + "\r"
+ "Sample Received Date: " + document.getElementById(re.......
it escapes out of the function
what am i doing wrong? how can i get the values of all the controls?
You need to use a lowercase "v" for value and quote your element ids. Eg:
document.getElementById("received_dateTextbox").value
Since it appears you are already using jQuery, you can make your code a little more concise. So document.getElementById("received_dateTextbox").value becomes:
$("#received_dateTextbox").val()
There is no variable named spec_idTextBox.
You probably want to pass a string literal.
Once you fix that, you need to use .value in lowercase
If you are using dynamic client ids, you have to render the ids inline or pass them to your function:
confirmationMessage = "Please review the data before submitting:" + "\r"
+ "Sample Received Date: " + document.getElementById('<% = received_dateTextbox.ClientID %>').value + "\r"
+ "Site of Ocurrence: " + document.getElementById('<% = site_of_occurrenceTextBox.ClientID %>').value + "\r"
+ "Occurrence Date: " + document.getElementById('<% = occurrence_dateTextBox.ClientID %>').value + "\r"
+ "Report Date: " + document.getElementById('<% = report_byTextBox.ClientID %>').value + "\r"
+ "Specimen ID: " + document.getElementById('<% = spec_idTextBox.ClientID %>').value + "\r"
+ "Batch ID: " + document.getElementById('<% = batch_idTextBox.ClientID %>').value + "\r\n"
+ "Report Initiated By: " + document.getElementById('<% = report_byTextBox.ClientID %>').value + "\r\n"
+ "Problem Identified By: " + $("input[#name=RadioButtonList1]:checked").val() + "\r\n"
+ "Problem List: " + nodeText;
I have the following bits of code:
public static void WriteHTML(string cFile, List<Movie> mList)
{
int lineID = 0;
string strMovie, strGenre, tmpGenre = null;
// initiates streamwriter for catalog output file
FileStream fs = new FileStream(cFile, FileMode.Create);
StreamWriter catalog = new StreamWriter(fs);
string strHeader = "<style type=\"text/css\">\r\n" + "<!--\r\n" + "tr#odd {\r\n" + " background-color:#e2e2e2;\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "\r\n" + "tr#even {\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "div#title {\r\n" + " font-size:16px;\r\n" + " font-weight:bold;\r\n" + "}\r\n" + "\r\n" + "div#mpaa {\r\n" + " font-size:10px;\r\n" + "}\r\n" + "\r\n" + "div#genre {\r\n" + " font-size:12px;\r\n" + " font-style:italic;\r\n" + "}\r\n" + "\r\n" + "div#plot {\r\n" + " height: 63px;\r\n" + " font-size:12px;\r\n" + " overflow:hidden;\r\n" + "}\r\n" + "-->\r\n" + "</style>\r\n" + "\r\n" + "<html>\r\n" + " <body>\r\n" + " <table>\r\n";
catalog.WriteLine(strHeader);
foreach (Movie m in mList)
{
strMovie = lineID == 0 ? " <tr id=\"odd\" style=\"page-break-inside:avoid\">" : " <tr id=\"even\" style=\"page-break-inside:avoid\">";
catalog.WriteLine(strMovie);
foreach (string genre in m.Genres)
tmpGenre += ", " + genre;
try
{ strGenre = tmpGenre.Substring(2); }
catch (Exception)
{ strGenre = null; }
strMovie = " <td>\r\n" + " <img src=\".\\images\\" + m.ImageFile + "\" width=\"75\" height=\"110\">\r\n" + " </td>\r\n" + " <td>\r\n" + " <div id=\"title\">" + m.Title + "</div>\r\n" + " <div id=\"mpaa\">" + m.Certification + " " + m.MPAA + "</div>\r\n" + " <div id=\"genre\">" + strGenre + "</div>\r\n" + " <div id=\"plot\">" + m.Plot + "</div>\r\n" + " </td>\r\n" + " </tr>\r\n";
catalog.WriteLine(strMovie);
lineID = lineID == 0 ? 1 : 0;
}
catalog.WriteLine(" </table>\r\n" + " </body>\r\n" + "</html>");
catalog.Close();
}
public static void WritePDF(string cFile, string pdfFile)
{
// Sets up PDF to write to
EO.Pdf.HtmlToPdf.Options.PageSize = new SizeF(8.5f, 11f);
EO.Pdf.HtmlToPdf.Options.OutputArea = new RectangleF(0.5f, .25f, 7.5f, 10.25f);
HtmlToPdf.ConvertUrl(cFile, pdfFile);
}
My HTML file writes fine, but when it tried to convert the HTML file to PDF I get an exception that it times out.
I did a test previously, and had it convert the code (not the file) within the WriteHTML function and it worked great. I have confirmed that the cFile exists and is a valid file (created previously in WriteHTML). The path to pdfFile is valid, and the documentation does not state the file needs to already exist (.ConvertHTML did not need an existing file).
Only thing I can think of is that the catalog.html file isn't released and ready to read yet. I made sure I closed it in the WriteHTML function. How can I test that the file is ready to be read?
Tried setting .MaxLoadWaitTime = 120000 with no luck.
Any clues would be greatly appreciated!
After a battery of further testing, and scouring the EO support forums, it appears to be a limitation of the free version of EO. It seems to have difficulty with HTML files over 3MB.
It's a shame since the EO product is very good, but not unfortunately not worth $250 IMO.
I am generating HTML files on the fly, and I would like to create a PDF from the final file. I am using the following to generate the HTML file:
public static void WriteHTML(string cFile, List<Movie> mList)
{
int lineID = 0;
string strHeader, strMovie, strGenre, tmpGenre = null;
string strPDF = null;
// initiates streamwriter for catalog output file
FileStream fs = new FileStream(cFile, FileMode.Create);
StreamWriter catalog = new StreamWriter(fs);
strHeader = "<style type=\"text/css\">\r\n" + "<!--\r\n" + "tr#odd {\r\n" + " background-color:#e2e2e2;\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "\r\n" + "tr#even {\r\n" + " vertical-align:top;\r\n" + "}\r\n" + "div#title {\r\n" + " font-size:16px;\r\n" + " font-weight:bold;\r\n" + "}\r\n" + "\r\n" + "div#mpaa {\r\n" + " font-size:10px;\r\n" + "}\r\n" + "\r\n" + "div#genre {\r\n" + " font-size:12px;\r\n" + " font-style:italic;\r\n" + "}\r\n" + "\r\n" + "div#plot {\r\n" + " height: 63px;\r\n" + " font-size:12px;\r\n" + " overflow:hidden;\r\n" + "}\r\n" + "-->\r\n" + "</style>\r\n" + "\r\n" + "<html>\r\n" + " <body>\r\n" + " <table>\r\n";
catalog.WriteLine(strHeader);
strPDF = strHeader;
foreach (Movie m in mList)
{
tmpGenre = null;
strMovie = lineID == 0 ? " <tr id=\"odd\" style=\"page-break-inside:avoid\">\r\n" : " <tr id=\"even\" style=\"page-break-inside:avoid\">\r\n";
catalog.WriteLine(strMovie);
strPDF += strMovie;
foreach (string genre in m.Genres)
tmpGenre += ", " + genre + "";
strGenre = tmpGenre != null ? tmpGenre.Substring(2) : null;
strMovie = " <td>\r\n" + " <img src=\".\\images\\" + m.ImageFile + "\" width=\"75\" height=\"110\">\r\n" + " </td>\r\n" + " <td>\r\n" + " <div id=\"title\">" + m.Title + "</div>\r\n" + " <div id=\"mpaa\">" + m.Certification + " " + m.MPAA + "</div>\r\n" + " <div id=\"genre\">" + strGenre + "</div>\r\n" + " <div id=\"plot\">" + m.Plot + "</div>\r\n" + " </td>\r\n" + " </tr>\r\n";
catalog.WriteLine(strMovie);
strPDF += strMovie;
lineID = lineID == 0 ? 1 : 0;
}
string closingHTML = " </table>\r\n" + " </body>\r\n" + "</html>";
catalog.WriteLine(closingHTML);
strPDF += closingHTML;
WritePDF(strPDF, cFile + ".PDF");
catalog.Close();
}
Once completed, I want to call the following function to generate the PDF file:
public static void WritePDF(string cFile, string pdfFile)
{
WkHtmlToPdfConverter w = new WkHtmlToPdfConverter();
byte[] strHTML = w.Convert(cFile);
File.WriteAllBytes(pdfFile, strHTML);
w.Dispose();
}
I've discovered that the .Convert function will convert HTML code to PDF, not a file. Secondly, when I pass in the HTML code directly, the images are not appearing in the PDF. I know there is an issue with .GIF files, but these are all .JPG files.
I've read a lot about how good wkhtmltopdf is, and the guy who wrote WkHTMLToSharp posted his project all over SO, but I've been disappointed by the lack of documentation for it.
I WANT to be able to pass in a file to convert, change the margins (I know this is possible, I just need to figure out the correct settings), have it convert images correctly, and most importantly, to not break up my items across multiple pages (support "page-break-inside:avoid" or something similar).
I'd love to see how others are using this!
I have coded an example about how to create a PDF from HTML. I just updated it to also print images.
https://github.com/hmadrigal/playground-dotnet/tree/master/MsDotNet.PdfGeneration
(In my blog post I explain most of the project https://hmadrigal.wordpress.com/2015/10/16/creating-pdf-reports-from-html-using-dotliquid-markup-for-templates-and-wkhtmltoxsharp-for-printing-pdf/ )
Pretty much you have two options:
1: Using file:// and the fullpath to the file.
<img alt="profile" src="{{ employee.PorfileFileName | Prepend: "Assets\ProfileImage\" | ToLocalPath }}" />
2: Using URL Data (https://en.wikipedia.org/wiki/Data_URI_scheme)
<img alt="profile" src="data:image/png;base64,{{ employee.PorfileFileName | Prepend: "Assets\ProfileImage\" | ToLocalPath | ToBase64 }}" />
Cheers,
Herb
Use WkHtmlToXSharp.
Download the latest DLL from Github
public static string ConvertHTMLtoPDF(string htmlFullPath, string pageSize, string orientation)
{
string pdfUrl = htmlFullPath.Replace(".html", ".pdf");
try
{
#region USING WkHtmlToXSharp.dll
//IHtmlToPdfConverter converter = new WkHtmlToPdfConverter();
IHtmlToPdfConverter converter = new MultiplexingConverter();
converter.GlobalSettings.Margin.Top = "0cm";
converter.GlobalSettings.Margin.Bottom = "0cm";
converter.GlobalSettings.Margin.Left = "0cm";
converter.GlobalSettings.Margin.Right = "0cm";
converter.GlobalSettings.Orientation = (PdfOrientation)Enum.Parse(typeof(PdfOrientation), orientation);
if (!string.IsNullOrEmpty(pageSize))
converter.GlobalSettings.Size.PageSize = (PdfPageSize)Enum.Parse(typeof(PdfPageSize), pageSize);
converter.ObjectSettings.Page = htmlFullPath;
converter.ObjectSettings.Web.EnablePlugins = true;
converter.ObjectSettings.Web.EnableJavascript = true;
converter.ObjectSettings.Web.Background = true;
converter.ObjectSettings.Web.LoadImages = true;
converter.ObjectSettings.Load.LoadErrorHandling = LoadErrorHandlingType.ignore;
Byte[] bufferPDF = converter.Convert();
System.IO.File.WriteAllBytes(pdfUrl, bufferPDF);
converter.Dispose();
#endregion
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return pdfUrl;
}
You can use Spire.Pdf to do so.
This component could convert html to pdf.
PdfDocument pdfdoc = new PdfDocument();
pdfdoc.LoadFromHTML(fileFullName, true, true, true);
//String url = "http://www.e-iceblue.com/";
//pdfdoc.LoadFromHTML(url, false, true, true);
pdfdoc.SaveToFile("FromHTML.pdf");
We're also using wkhtmltopdf and are able to render images correctly. However, by default the rendering of images is disabled.
You have to specify those options on your converter instance:
var wk = _GetConverter()
wk.GlobalSettings.Margin.Top = "20mm";
wk.GlobalSettings.Margin.Bottom = "10mm";
wk.GlobalSettings.Margin.Left = "10mm";
wk.GlobalSettings.Margin.Right = "10mm";
wk.GlobalSettings.Size.PaperSize = PdfPaperSize.A4;
wk.ObjectSettings.Web.PrintMediaType = true;
wk.ObjectSettings.Web.LoadImages = true;
wk.ObjectSettings.Web.EnablePlugins = false;
wk.ObjectSettings.Web.EnableJavascript = true;
result = wk.Convert(htmlContent);