I am trying to save a PDF file to a server path rather than downloading it as an attachment, which I have made with the "hiqpdf" tool. :
protected void btnPrint_Click(object sender, EventArgs e)
{
// create the HTML to PDF converter
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
// set browser width
htmlToPdfConverter.BrowserWidth = int.Parse("805");
// set browser height if specified, otherwise use the default
//if (textBoxBrowserHeight.Text.Length > 0)
// htmlToPdfConverter.BrowserHeight = int.Parse(textBoxBrowserHeight.Text);
// set HTML Load timeout
htmlToPdfConverter.HtmlLoadedTimeout = int.Parse("180");
// set PDF page size and orientation
htmlToPdfConverter.Document.PageSize = PdfPageSize.A4;
htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait;
// set PDF page margins
htmlToPdfConverter.Document.Margins = new PdfMargins(0);
// set a wait time before starting the conversion
htmlToPdfConverter.WaitBeforeConvert = int.Parse("5");
// convert HTML to PDF
byte[] pdfBuffer = null;
//if (radioButtonConvertUrl.Checked)
//{
// convert URL to a PDF memory buffer
string url = System.Configuration.ConfigurationManager.AppSettings["SiteURL"] + "PrintFullApplicantProfile.aspx?MaidID=" + Request.QueryString["aid"].ToString();
pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory(url);
// inform the browser about the binary data format
HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf");
// let the browser know how to open the PDF document, attachment or inline, and the file name
//HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=HtmlToPdf.pdf; size={1}",
// checkBoxOpenInline.Checked ? "inline" : "attachment", pdfBuffer.Length.ToString()));
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=Applicant-" + Request.QueryString["aid"].ToString() + ".pdf; size={1}", "attachment", pdfBuffer.Length.ToString()));
// write the PDF buffer to HTTP response
HttpContext.Current.Response.BinaryWrite(pdfBuffer);
// call End() method of HTTP response to stop ASP.NET page processing
HttpContext.Current.Response.End();
}
Any suggestion to save the file to the server path?
Thanks in advance.
Related
I need to generate a pdf report from a URL in our application. Is it possible to have both Landscape and Portrait pages in the same pdf document that is generated?
I'd like to have the bar charts as Portrait, and the Tables as Landscape (horizontal). Looking at the EVO doc's I don't know if this is possible.
I know that you can define either Landscape or Portrait with
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation
But this is applied to the whole document. I'd like something I could potentially define the html that would tell EVO to print this section as Landscape.
You can have Portrait and Landscape section in the same PDF. For this you can create a blank Document object and add a PDF page with the desired orientation to this document. On the newly created PDF page you can add a HtmlToPdfElement object to render the HTML and automatically add PDF pages with the same orientation with the PDF page you initially created. The procedure can be repeated with PDF pages of different orientations. There is a live sample with C# code for this approach in Merge Multiple HTML Pages into a Single PDF demo. The code sample is also copied below:
protected void convertToPdfButton_Click(object sender, EventArgs e)
{
// Create the PDF document where to add the HTML documents
Document pdfDocument = new Document();
// Create a PDF page where to add the first HTML
PdfPage firstPdfPage = pdfDocument.AddPage();
try
{
// Create the first HTML to PDF element
HtmlToPdfElement firstHtml = new HtmlToPdfElement(0, 0, firstUrlTextBox.Text);
// Optionally set a delay before conversion to allow asynchonous scripts to finish
firstHtml.ConversionDelay = 2;
// Add the first HTML to PDF document
AddElementResult firstAddResult = firstPdfPage.AddElement(firstHtml);
PdfPage secondPdfPage = null;
PointF secondHtmlLocation = Point.Empty;
if (startNewPageCheckBox.Checked)
{
// Create a PDF page where to add the second HTML
secondPdfPage = pdfDocument.AddPage();
secondHtmlLocation = PointF.Empty;
}
else
{
// Add the second HTML on the PDF page where the first HTML ended
secondPdfPage = firstAddResult.EndPdfPage;
secondHtmlLocation = new PointF(firstAddResult.EndPageBounds.Left, firstAddResult.EndPageBounds.Bottom);
}
// Create the second HTML to PDF element
HtmlToPdfElement secondHtml = new HtmlToPdfElement(secondHtmlLocation.X, secondHtmlLocation.Y, secondUrlTextBox.Text);
// Optionally set a delay before conversion to allow asynchonous scripts to finish
secondHtml.ConversionDelay = 2;
// Add the second HTML to PDF document
secondPdfPage.AddElement(secondHtml);
// Save the PDF document in a memory buffer
byte[] outPdfBuffer = pdfDocument.Save();
// Send the PDF as response to browser
// Set response content type
Response.AddHeader("Content-Type", "application/pdf");
// Instruct the browser to open the PDF file as an attachment or inline
Response.AddHeader("Content-Disposition", String.Format("attachment; filename=Merge_Multipe_HTML.pdf; size={0}", outPdfBuffer.Length.ToString()));
// Write the PDF document buffer to HTTP response
Response.BinaryWrite(outPdfBuffer);
// End the HTTP response and stop the current page processing
Response.End();
}
finally
{
// Close the PDF document
pdfDocument.Close();
}
}
while downloading html code into pdf in selectpdf software. im getting error saying - "Conversion error: Could not open url".im using selectpdf for converting html code to pdf. what is the base url i have to give .
using SelectPdf;
public partial class HtmlcodePrint : System.Web.UI.Page
{
string TxtHtmlCode;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TxtHtmlCode = #"<html>
<body>
Hello World from selectpdf.com.
</body>
</html>
";
}
}
protected void Btndownloadpdf_Click(object sender, EventArgs e)
{
// read parameters from the webpage
string htmlString = TxtHtmlCode;
string baseUrl = "http://localhost:51868/HtmlcodePrint.aspx";
string pdf_page_size ="A4";
PdfPageSize pageSize = (PdfPageSize)Enum.Parse(typeof(PdfPageSize),
pdf_page_size, true);
string pdf_orientation = "Portrait";
PdfPageOrientation pdfOrientation =
(PdfPageOrientation)Enum.Parse(typeof(PdfPageOrientation),
pdf_orientation, true);
int webPageWidth = 1024;
try
{
webPageWidth = Convert.ToInt32("1024");
}
catch { }
int webPageHeight = 0;
try
{
webPageHeight = Convert.ToInt32("777");
}
catch { }
// instantiate a html to pdf converter object
HtmlToPdf converter = new HtmlToPdf();
// set converter options
converter.Options.PdfPageSize = pageSize;
converter.Options.PdfPageOrientation = pdfOrientation;
converter.Options.WebPageWidth = webPageWidth;
converter.Options.WebPageHeight = webPageHeight;
// create a new pdf document converting an url
PdfDocument doc = converter.ConvertHtmlString(htmlString, baseUrl);
// save pdf document
doc.Save(Response, false, "Sample.pdf");
// close pdf document
doc.Close();
}
}
I know this is old, but I've been working with SelectPdf for a couple of days, so I'll throw in my 2 cents.
You probably don't need a baseUrl...
You don't have to give any baseUrl at all to the ConvertHtmlString function. You can just pass it the html string you want to convert and that's it.
Unless...
You only need to pass it a baseUrl if the html you're converting has relative paths in the external references (example: if you were referencing a stylesheet and wanted to use a relative path, you could provide the baseUrl to show where you wanted the stylesheet to be relative to). It's just so the converter can create the full absolute paths from the relative paths.
So...
If you don't need that functionality or just don't have external references in your html, then you can just use
converter.ConvertHtmlString(htmlString);
Also...
doc.Save(Response, false, "Sample.pdf");
may not be what you're looking for either. I only say this because the comments look like the same ones on the examples on the site for SelectPDF, so I'm assuming you copied the code from there (which is what I originally did too), in which case I want to let you know you don't have to save your PDF doc with that particular version of Save. It actually has 3 overloads to allow you to save your doc as:
a byte array (default)
a stream
a file
an HTTP response (the one you're using now, as shown in the examples from the site)
So, like I pointed out, you're using the one that saves the PDF as a HTTP response, so if you're wanting to save it as an actual PDF file directly, you'll need to change it to
doc.Save(fileName)
with the fileName variable as the absolute or relative path or file name you want to save the PDF to.
Hope this helps
I'm at the last step in completing a pdf generator. I am using iText sharp and i am able to stamp a base64 image with no problem thanks to help from StackOverflow.
My question is how would I iterate over posted files and add a new page with posted image files on it. Here is my current way of stamping an image... however, its coming from base64. I need to add uploaded images selected from my application to the pdf preferably while the stamper is opened. Just can't seem to make my code work.
I feel this is easy to iterate thru but can't get the logic. Please help:
PdfContentByte pdfContentByte = stamper.GetOverContent(1);
PdfContentByte pdfContentByte2 = stamper.GetOverContent(4);
var image = iTextSharp.text.Image.GetInstance(
Convert.FromBase64String(match.Groups["data"].Value)
);
image.SetAbsolutePosition(270, 90);
image.ScaleToFit(250f, 100f);
pdfContentByte.AddImage(image);
//stamping base64 image works perfect - now i need to stamp the uploaded images onto a new page in the same document before stamper closes.
var imagepath = "//test//";
HttpFileCollection uploadFilCol = HttpContext.Current.Request.Files;
for (int i = 0; i < uploadFilCol.Count; i++)
{
HttpPostedFile file = uploadFilCol[i];
using (FileStream fs = new FileStream(imagepath + "Invoice-" +
HttpContext.Current.Request.Form.Get("genUUID") + file, FileMode.Open))
{
HttpPostedFile file = uploadFilCol[i];
pdfContentByte2.AddImage(file);
}
}
My posted files comes from input form on an html page
<input type="file" id="file" name="files[]" runat="server" multiple />
The basic steps:
Iterate over the HttpFileCollection.
Read each HttpPostedFile into a byte array.
Create iText Image with byte array in previous step.
Set the image absolute position, and optionally scale as needed.
Add image at specified page number with GetOverContent()
A quick snippet to get you started. Not tested, and assumes you have PdfReader, Stream, and PdfStamper setup, along with a working file upload:
HttpFileCollection uploadFilCol = HttpContext.Current.Request.Files;
for (int i = 0; i < uploadFilCol.Count; i++)
{
HttpPostedFile postedFile = uploadFilCol[i];
using (var br = new BinaryReader(postedFile.InputStream))
{
var imageBytes = br.ReadBytes(postedFile.ContentLength);
var image = Image.GetInstance(imageBytes);
// still not sure if you want to add a new blank page, but
// here's how
//stamper.InsertPage(
// APPEND_NEW_PAGE_NUMBER, reader.GetPageSize(APPEND_NEW_PAGE_NUMBER - 1)
//);
// image absolute position
image.SetAbsolutePosition(absoluteX, absoluteY);
// scale image if needed
// image.ScaleAbsolute(...);
// PAGE_NUMBER => add image to specific page number
stamper.GetOverContent(PAGE_NUMBER).AddImage(image);
}
}
I am using HiQPdf to convert and combine a list of html page into one pdf document.
this is how i'm doing this:
public class HtmlToPdfEditor
{
private string _firstPage;
private string _secondPage;
//private const string _HiQPdfSerialNumber = "";
private PdfDocument _document;
public HtmlToPdfEditor(string firstPage, string secondPage)
{
_firstPage = firstPage;
_secondPage=secondPage;
}
public void ConvertAll(string outputPath)
{
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
_document = new PdfDocument();
//_document.SerialNumber = _HiQPdfSerialNumber;
string firstPageDoc = GetDocument(_firstPage, "firstPage.pdf");
string secondPageDoc = GetDocument(_secondPage, "secondtPage.pdf");
this.JoinDocument(PdfFromFile(firstPageDoc));
this.JoinDocument(PdfFromFile(secondPageDoc));
_document.WriteToFile(outputPath);
_document.Close();
_document = null;
}
private PdfDocument PdfFromFile(string path)
{
return PdfDocument.FromFile(path);
}
private int JoinDocument(PdfDocument document)
{
var nbPages = _document.Pages.Count;
_document.AddDocument(document);
document.Close();
return nbPages;
}
private string GetDocument(string content, string outputFile)
{
var baseUrl = "";
var htmlToPdfConverter = GetPdfExporter();
htmlToPdfConverter.ConvertHtmlToFile(content, baseUrl, outputFile);
return outputFile;
}
public HtmlToPdf GetPdfExporter()
{
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
//htmlToPdfConverter.SerialNumber = _HiQPdfSerialNumber;
htmlToPdfConverter.Document.PageSize = PdfPageSize.A4;
htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait;
htmlToPdfConverter.Document.Margins = new PdfMargins(2);
htmlToPdfConverter.HtmlLoadedTimeout = 60;
htmlToPdfConverter.TriggerMode = ConversionTriggerMode.WaitTime; //Time to load the html
htmlToPdfConverter.WaitBeforeConvert = 1;
return htmlToPdfConverter;
}
}
The issue here is that in the resulting document the page converted from html are displayed as empty pages, only google chrome display them correctly , in firefox these pages continue indefinitely in the loading state.
Notice that if I convert the Html to a PdfDocument instead of storing it to a file and then joining it. The resulting document is perfectly readable but unfortunately I can't use this method.
Any help will be much apreciated!! thx!!
Yes, that's correct, the PDF documents you add to a main document must remain opened until you close the main document.
If the PDF documents you merge are produced from HTML there is actually an easier way to merge the HTML documents in a PDF following the approach from Convert Many HTML to PDF example.
// create an empty PDF document
PdfDocument document = new PdfDocument();
// add a page to document
PdfPage page1 = document.AddPage(PdfPageSize.A4, new PdfDocumentMargins(5),
PdfPageOrientation.Portrait);
try
{
// set the document header and footer before
// adding any objects to document
SetHeader(document);
SetFooter(document);
// layout the HTML from URL 1
PdfHtml html1 = new PdfHtml(textBoxUrl1.Text);
PdfLayoutInfo html1LayoutInfo = page1.Layout(html1);
// determine the PDF page where to add URL 2
PdfPage page2 = null;
System.Drawing.PointF location2 = System.Drawing.PointF.Empty;
if (checkBoxNewPage.Checked)
{
// URL 2 is laid out on a new page with the selected orientation
page2 = document.AddPage(PdfPageSize.A4, new PdfDocumentMargins(5),
GetSelectedPageOrientation());
location2 = System.Drawing.PointF.Empty;
}
else
{
// URL 2 is laid out immediately after URL 1 and html1LayoutInfo
// gives the location where the URL 1 layout finished
page2 = document.Pages[html1LayoutInfo.LastPageIndex];
location2 = new System.Drawing.PointF(html1LayoutInfo.LastPageRectangle.X,
html1LayoutInfo.LastPageRectangle.Bottom);
}
// layout the HTML from URL 2
PdfHtml html2 = new PdfHtml(location2.X, location2.Y, textBoxUrl2.Text);
page2.Layout(html2);
// write the PDF document to a memory buffer
byte[] pdfBuffer = document.WriteToMemory();
// inform the browser about the binary data format
HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf");
// let the browser know how to open the PDF document
HttpContext.Current.Response.AddHeader("Content-Disposition",
String.Format("attachment; filename=LayoutMultipleHtml.pdf;
size={0}",
pdfBuffer.Length.ToString()));
// write the PDF buffer to HTTP response
HttpContext.Current.Response.BinaryWrite(pdfBuffer);
// call End() method of HTTP response
// to stop ASP.NET page processing
HttpContext.Current.Response.End();
}
finally
{
document.Close();
}
Ok I resolved this issue by ensuring that all pdf documents to be merged are closed after closing the final document. In other words the method JoinDocument will no longer call document.Close(). I'll call it later after closing the final document (_document).
I've got the problem as below:
There is some SOAP web service which allows to read stream files. I need to read the whole file divided to chunks and transmit to user. All actions should do not block UI main thread: user presses 'Save' button on save file dialog, and is able to move on to the next page or perform another action. I will be grateful for the sample solution. Note that the solution should work with IIS 5.1.
Regards,
Jimmy
Downloading a file in ASP.NET byte-by-byte to the response page. check at msdn about this:
try
{
System.String filename = "C:\\downloadJSP\\myFile.txt";
// set the http content type to "APPLICATION/OCTET-STREAM
Response.ContentType = "APPLICATION/OCTET-STREAM";
// initialize the http content-disposition header to
// indicate a file attachment with the default filename
// "myFile.txt"
System.String disHeader = "Attachment;
Filename=\"myFile.txt\"";
Response.AppendHeader("Content-Disposition", disHeader);
// transfer the file byte-by-byte to the response object
System.IO.FileInfo fileToDownload = new
System.IO.FileInfo(filename);
System.IO.FileStream fileInputStream = new
System.IO.FileStream(fileToDownload.FullName,
System.IO.FileMode.Open, System.IO.FileAccess.Read);
int i;
while ((i = fileInputStream.ReadByte()) != - 1)
{
Response.Write((char)i);
}
fileInputStream.Close();
Response.Flush();
Response.Close();
}
catch (System.Exception e)
// file IO errors
{
SupportClass.WriteStackTrace(e, Console.Error);
}
There are some articles that may help you to implement and solve errors:
download an excel file from byte() on https server
asp.net downloading file from ftp getting it as byte[] then saving it as file
Remote file Download via ASP.NET corrupted file
Response.WriteFile cannot download a large file
ProcessRequest method form downloader HttpHandler:
public void ProcessRequest(HttpContext context)
{
RequestTarget target = RequestTarget.ParseFromQueryString(context.Request.QueryString);
Guid requestId = new Guid(context.Request.QueryString["requestId"]);
string itemName = HttpUtility.UrlDecode(context.Request.QueryString["itemName"]);
if (target != null &&
!requestId.Equals(Guid.Empty) &&
!string.IsNullOrEmpty(itemName))
{
HttpResponse response = context.Response;
response.Buffer = false;
response.Clear();
response.AddHeader("Content-Disposition", "attachment;filename=\"" + itemName + "\"");
response.ContentType = "application/octet-stream";
int length = 100000, i = 0;
byte[] fileBytes;
do
{
fileBytes = WS.ReadFile(requestId, target, i * length, length);
i++;
response.OutputStream.Write(fileBytes, 0, fileBytes.Length);
response.Flush();
}
while (fileBytes != null && fileBytes.Length == length);
}
}
The whole problem is not to organize download action, but satisfy the condition that download action should do not block UI main thread: user presses 'Save' button on save file dialog, and is able to move on to the next page or perform another action. The solution written by Niranjan Kala causes, when the file is very large user isn't able to see another page until the download action has completed. I appreciate it, but it's not what I meant ...
If I understand you correctly, you want to make the browser initiate a new request for the file without reloading the current page. The easiest approach is probably to just create a link with target="_blank". Something like this should do:
Download file
If you provide a content type of application/octet-stream most browsers will save the file to disk.