My goal is to generate the aspx code of a page in the form of string.I am calling the below codebehind code through asynchronous request in javascript and i am getting the response back through Response.Write
string html = string.Empty;
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
{
var htmlWriter = new HtmlTextWriter(streamWriter);
base.Render(htmlWriter);
htmlWriter.Flush();
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
html = streamReader.ReadToEnd();
streamReader.Close();
}
}
}
Response.Write(html);
Response.End();
I want to ask that is the above code is memory efficient, I am thinking of "yield" to use as it evaluates lazily.Can u suggest on memory efficency of above code.
Use a StringWriter instead of the MemoryStream, the StreamWriter and the StreamReader:
string html;
using (StringWriter stream = new StringWriter()) {
using (HtmlTextWriter writer = new HtmlTextWriter(stream)) {
base.Render(writer);
}
html = stream.ToString();
}
Response.Write(html);
Response.End();
The StringWriter uses a StringBuilder internally. The ToString method calls ToString on the Stringuilder, so it returns the internal string buffer as the string. That means that the string is only created once, and not copied back and forth.
Your method stores an html copy at html variable, and another at memoryStream. Try this:
base.Render(new HtmlTextWriter(Response.Output));
Response.End();
While this can work, I'm not sure what are you trying to accomplish.
Related
I am new to Aspose but I have successfully converted several file formats into PDF's but I am struck with HTML to PDF conversion. I am able to convert a HTML file into a PDF successfully but the CSS part is not rendering into the generated PDF. Any idea on this? I saved www.google.com as my input HTML file. Here is my controller code.
using Aspose.Pdf.Generator
Pdf pdf = new Pdf();
pdf.HtmlInfo.CharSet = "UTF-8";
Section section = pdf.Sections.Add();
StreamReader r = File.OpenText(#"Local HTML File Path");
Text text2 = new Aspose.Pdf.Generator.Text(section, r.ReadToEnd());
pdf.HtmlInfo.ExternalResourcesBasePath = "Local HTML File Path";
text2.IsHtmlTagSupported = true;
text2.IsFitToPage = true;
section.Paragraphs.Add(text2);
pdf.Save(#"Generated PDF File Path");
Am i missing something? Any kind of help is greatly appreciated.
Thanks
My name is Tilal Ahmad and I am developer evangelist at Aspose.
Please use new DOM approach(Aspose.Pdf.Document) for HTML to PDF conversion. In this approach to render external resources(CSS/Images/Fonts) you need to pass resources path to HtmlLoadOptions() method. Please check following documentation links for the purpose.
Convert HTML to PDF (new DOM)
HtmlLoadOptions options = new HtmlLoadOptions(resourcesPath);
Document pdfDocument = new Document(inputPath, options);
pdfDocument.Save("outputPath");
Convert Webpage to PDF(new DOM)
// Create a request for the URL.
WebRequest request = WebRequest.Create("https:// En.wikipedia.org/wiki/Main_Page");
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
// Time out in miliseconds before the request times out
// Request.Timeout = 100;
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
MemoryStream stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(responseFromServer));
HtmlLoadOptions options = new HtmlLoadOptions("https:// En.wikipedia.org/wiki/");
// Load HTML file
Document pdfDocument = new Document(stream, options);
options.PageInfo.IsLandscape = true;
// Save output as PDF format
pdfDocument.Save(outputPath);
Try using media attribute in each style tag
<style media="print">
and then provide the html file to your Aspose.Pdf Generator.
Try this.. This is working nice for me
var license = new Aspose.Pdf.License();
license.SetLicense("Aspose.Pdf.lic");
var license = new Aspose.Html.License();
license.SetLicense("Aspose.Html.lic");
using (MemoryStream memoryStream = new MemoryStream())
{
var options = new PdfRenderingOptions();
using (PdfDevice pdfDevice = new PdfDevice(options, memoryStream))
{
using (var renderer = new HtmlRenderer())
{
using (HTMLDocument htmlDocument = new HTMLDocument(content, ""))
{
renderer.Render(pdfDevice, htmlDocument);
//Save memoryStream into output pdf file
}
}
}
}
content is string type which is my html content.
I am doing html to pdf file . Its Downloading instantly . I dont want download instantly. i want to save the file in my project folder once converted.
My C# Code
string html ="<table><tr><td>some contents</td></tr></table>";
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
StringReader sr = new StringReader(table);
Document ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30);
PdfPTable Headtable = new PdfPTable(7);
Headtable.TotalWidth = 525f;
Headtable.LockedWidth = true;
Headtable.HeaderRows = 5;
Headtable.FooterRows = 2;
Headtable.KeepTogether = true;
HTMLWorker htmlparser = new HTMLWorker(ResultPDF);
PdfWriter.GetInstance(ResultPDF, Response.OutputStream);
ResultPDF.Open();
htmlparser.Parse(sr);
ResultPDF.Close();
Response.Write(ResultPDF);
Response.End();
For saving pdf file locally in your project folder you can use FileStream class like this.
FileStream stream = new FileStream(filePath, FileMode.Create);//Here filePath is path of your project folder.
Now use this stream instead of using Response.OutputStream when you create instance of PdfWriter object.
PdfWriter.GetInstance(ResultPDF, stream);
Now do not use Responce.Write as you don't want to download your file.And close your stream at end.
stream.Close();
I'm going to combine everyone's answer into one that you should be able to drop in and use. If this works, I would accept Manish Parakhiya's answer because that had the most important part.
First, I'm going to assume you are using a recent version of iTextSharp. I think 5.5.5 is the most recent version. Second, because of this, I'm going to restructure your code a bit in order to use the using pattern. If you're stuck on an older obsolete unsupported version like 4.1.6 you'll need to re-adjust.
Almost every tutorial out there shows you that you can bind directly the Response.OutputStream. This is 100% valid but I would argue that it is also a really bad idea. Instead, bind to a more generic MemoryStream. This makes debugging much easier and your code will port and adapt that much easier.
The below code includes comments about each of the changes and what things are actually doing. The top section is all about creating a PDF from a string of HTML. The bottom actually does something with it, including writing it to disk and/or streaming it to a browser.
//Will hold our PDF eventually
Byte[] bytes;
//HTML that we want to parse
string html = "<table><tr><td>some contents</td></tr></table>";
//Create a MemoryStream to write our PDF to
using (var ms = new MemoryStream()) {
//Create our document abstraction
using (var ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30)) {
//Bind a writer to our Document abstraction and our stream
using (var writer = PdfWriter.GetInstance(ResultPDF, ms)) {
//Open the PDF for writing
ResultPDF.Open();
//Parse our HTML using the old, obsolete, not support parser
using (var sw = new StringWriter()) {
using (var hw = new HtmlTextWriter(sw)) {
using (var sr = new StringReader(html)) {
using (var htmlparser = new HTMLWorker(ResultPDF)) {
htmlparser.Parse(sr);
}
}
}
}
//Close the PDF
ResultPDF.Close();
}
}
//Grab the raw bytes of the PDF
bytes = ms.ToArray();
}
//At this point, the bytes variable holds a valid PDF file.
//You can write it disk:
System.IO.File.WriteAllBytes("your file path here", bytes);
//You can also send it to a browser:
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.BinaryWrite(bytes);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
//Never do the next line, it doesn't do what you think it does and actually produces corrupt PDFs
//Response.Write(ResultPDF); //BAD!!!!!!
Response.End();
string tempDirectory = Session.SessionID.ToString();
string location = Path.Combine(Server.MapPath(
WebConfigurationManager.AppSettings["PathSet"].ToString()), tempDirectory);
if (!Directory.Exists(location))
{
Directory.CreateDirectory(location);
}
string fileName="abc.pdf";
filePath = Path.Combine(location, fileName);
I tried to write to CSV file using CsvHelper in C#.
This is the link to the library http://joshclose.github.io/CsvHelper/
I used the code in web site.
Here is my code:
var csv = new CsvWriter(writer);
csv.Configuration.Encoding = Encoding.UTF8;
foreach (var value in valuess)
{
csv.WriteRecord(value);
}
It writes only a part of data to csv file.
Last rows were missing.
Could you please help with this.
You need to flush the stream. The Using statement will flush when out of scope.
using (TextWriter writer = new StreamWriter(#"C:\test.csv", false, System.Text.Encoding.UTF8))
{
var csv = new CsvWriter(writer);
csv.WriteRecords(values); // where values implements IEnumerable
}
when, I added this code after the loop code is working well
var csv = new CsvWriter(writer);
csv.Configuration.Encoding = Encoding.UTF8;
foreach (var value in valuess)
{
csv.WriteRecord(value);
}
writer.Close();
The problem occurred because I did not close the Connection
Assuming that writer is some kind of TextWriter, you should add a call to flush the contents before closing the writer:
writer.Flush()
If the last lines are missing, this is the most likely reason.
Adding to #greg's answer:
using (var sr = new StreamWriter(#"C:\out.csv", false, Encoding.UTF8)) {
using (var csv = new CsvWriter(sr)) {
csv.WriteRecords(values);
}
}
I'm trying to save an xml file into a blob. I have no error, everything seems fine except when I navigate to the blob url I see a blank page. If I look at the source code of the web page I can see my xml but truncated.
Here is te code.
StringBuilder fileString = new StringBuilder();
XmlWriterSettings xmlSettings=new XmlWriterSettings
{
Encoding = new UTF8Encoding(false)
};
using (XmlWriter writer = XmlWriter.Create(fileString, xmlSettings))
{
bla bla
}
CloudBlockBlob fileBlob = container.GetBlockBlobReference("site.xml");
fileBlob.UploadText(fileString.ToString());
I found the solution in some other post (not so much the problem although it has to do with encoding of text always being utf-16 despite setting up the writer as utf-8). I am now using a Stream and it works fine.
MemoryStream fileString = new MemoryStream();
XmlWriterSettings xmlSettings=new XmlWriterSettings
{
Encoding = Encoding.UTF8,
Indent = true
};
using (XmlWriter writer = XmlWriter.Create(fileString, xmlSettings))
{
bla bla
}
CloudBlockBlob fileBlob = container.GetBlockBlobReference("site.xml");
fileBlob.UploadText(StreamToString(fileString));
private static string StreamToString(Stream stream)
{
stream.Position = 0;
var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
If you have decided to use a Stream, you can also upload it using UploadFromStream instead of UploadText, which encodes the string into a sequence of bytes, creates a memory stream, and calls UploadFromStream anyway.
Need to generate an html report from XML and corresponding XSL butI have to use memorystream instead of IO File write on server directories. For the most part I managed to create an xml
MemoryStream ms = new MemoryStream();
XmlWriterSettings wSettings = new XmlWriterSettings();
wSettings.Indent = true;
using(XmlWriter writer = XmlWriter.Create(ms,wSettings))
{
/**
creating xml here
**/
writer.Flush();
writer.Close();
}
return ms; // returning the memory stream to another function
// to create html
// This Function creates
protected string ConvertToHtml(MemoryStream xmlOutput)
{
XPathDocument document = new XPathDocument(xmlOutput);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xmlOutput);
StringWriter writer = new StringWriter();
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(reportDir + "MyXslFile.xsl");
transform.Transform(xDoc, null, writer);
xmlOutput.Position = 1;
StreamReader sr = new StreamReader(xmlOutput);
return sr.RearToEnd();
}
Somewhere along the line I am messing up with creating the HTML Report and cant figure out how to send that file to client end. I dont have much experience working with memorystream. So, any help would be greatly appreciated. Thank you.
You're completely bypassing your transform here:
// This Function creates
protected string ConvertToHtml(MemoryStream xmlOutput)
{
XPathDocument document = new XPathDocument(xmlOutput);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xmlOutput);
StringWriter writer = new StringWriter();
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(reportDir + "MyXslFile.xsl");
transform.Transform(xDoc, null, writer);
// These lines are the problem
//xmlOutput.Position = 1;
//StreamReader sr = new StreamReader(xmlOutput);
//return sr.RearToEnd();
return writer.ToString()
}
Also, calling Flush right before you call Close on a writer is redundant as Close implies a flush operation.
It is not clear to me what you want to achieve but using both XmlDocument and XPathDocument to load from the same memory stream does not make sense I think. And I would set the MemoryStream to Position 0 before loading from it so either have the function creating and writing to the memory stream ensure that it sets the Position to zero or do that before you call Load on the XmlDocument or before you create an XPathDocument, depending on what input tree model you want to use.