Print PDF Created using itextsharp - javascript

My Goal is to print a RDLC report on the client machine without preview. I can not use the ReportViewer print button since it requires the installation of ActiveX object and there are no permissions for that. So, I'm using ITextSharp to create a PDF from the byte array returned from the rendered LocalReport, and add a JavaScript for print.
During Debug, I can see that the PDF is generated and has 2 pages, and everything looks OK. I don't receive any errors and the function exits OK, but it doesn't print. What am I doing wrong, or what am I missing?
This is my code:
string jsPrint = "var pp = this.getPrintParams();pp.interactive= pp.constants.interactionLevel.silent;this.print(pp);";
byte[] bytes = report.Render("PDF", null, out mimeType, out encoding, out extension, out streamids, out warnings);
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
doc.SetPageSize(PageSize.A4);
doc.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
PdfReader reader = new PdfReader(bytes);
int pages = reader.NumberOfPages;
for (int i = 1; i <= pages; i++)
{
doc.SetPageSize(PageSize.A4);
doc.NewPage();
page = writer.GetImportedPage(reader, i);
cb.AddTemplate(page, 0, 0);
}
PdfAction jAction = PdfAction.JavaScript(jsPrint, writer);
writer.AddJavaScript(jAction);
doc.Close();
}
Thanks.

Regarding your question about PdfStamper (in the comments). It should be as simple as this:
string jsPrint = "var pp = this.getPrintParams();pp.interactive= pp.constants.interactionLevel.silent;this.print(pp);";
PdfReader reader = new PdfReader(bytes);
MemoryStream stream = new MemoryStream();
PdfStamper stamper = new PdfStamper(pdfReader, stream);
stamper.Writer.AddJavaScript(jsPrint);
stamper.Close();
reader.Close();
Regarding your original question: automatic printing of PDF documents is considered being a security hazard: one could send a PDF to an end-user and that PDF would cause the printer to spew out pages. That used to be possible with (really) old PDF viewers, but modern viewers prevent this from happening.
In other words: you may be trying to meet a requirement of the past. Today's PDF viewers always require an action from the end user to print a PDF document.

Related

How can I modify a javascript event in a PDF file programmatically?

My PDF file has an event attached to a button. I need to be able to modify that event programmatically. I tried this way using iTextSharp, but it didn't change the javascript in the new file:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(
newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None),
'\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace(
"Table2.Row1.instanceManager.removeInstance(1)",
"Table2._Row1.removeInstance(this.parent.parent.index)");
// Unfortunately, this line does nothing.
pdfStamper.AcroFields.Xfa.DomDocument.InnerXml = newXml;
pdfStamper.Close();
pdfReader.Close();
Any help would be greatly appreciated.
I found that it works if, instead of changing the XML directly, I change the DomDocument and mark the XFA as changed. Below is the corrected code:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None), '\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace("Table2.Row1.instanceManager.removeInstance(1)", "Table2._Row1.removeInstance(this.parent.parent.index)");
/* New Code */
var doc = new XmlDocument();
doc.LoadXml(newXml);
pdfStamper.AcroFields.Xfa.DomDocument = doc;
pdfStamper.AcroFields.Xfa.Changed = true;
/* End of New Code */
pdfStamper.Close();
pdfReader.Close();
I should note that, even though this code changes the javascript in the PDF file, it also disables the extended features in Adobe Acrobat Reader. You can find more information regarding this here:
http://developers.itextpdf.com/question/why-do-i-get-error-saying-use-extended-features-no-longer-available
"The problem is related to whether or not your document is Reader Enabled. Reader-enabling can only be done using Adobe software. It is a process that requires a digital signature using a private key from Adobe. When a valid signature is present, specific functionality (as defined in the usage rights when signing) is unlocked in Adobe Reader.
You change the content of such a PDF, hence you break the signature."

How to open (not save) a generated blob array of a pdf (Intel XDK-Android)?

I want to know a properly and proved way to open (not save) a generated blob array of a pdf with some default app for that (e.g. Adobe reader) if I am developing for Android with Intel XDK and Cordova.
Unsuccessfully I tried this (generated with jspdf):
function createPDF(){
console.log("generating pdf...");
var doc = new jsPDF();
doc.text(20, 20, 'HELLO!');
doc.setFont("courier");
doc.setFontType("normal");
doc.text(20, 30, 'This is a PDF document generated using JSPDF.');
doc.text(20, 50, 'YES, Inside of cordova!');
pdfOutput = doc.output();
console.log(pdfOutput);
var buffer = new ArrayBuffer(pdfOutput.length);
var array = new Uint8Array(buffer);
for (var i = 0; i < pdfOutput.length; i++) {
array[i] = pdfOutput.charCodeAt(i);
}
var pdfAsDataUri = "data:application/pdf;base64," + array;
window.open(pdfAsDataUri);
}
Also I tried a lot of example but nothing works, just in case, none error is shown in console.
Thank you all.
You can create a Blob from pdfOutput, then create a Blob URL from Blob using URL.createObjectURL()
var blob = new Blob([pdfOutput], {type:"application/pdf"});
var url = URL.createObjectURL(blob);
var pdfAsDataUri = url;
window.open(pdfAsDataUri);
plnkr http://plnkr.co/edit/xt5uVvskmcgSlf13xVVM?p=preview
Finally I can do it splitting the problem to:
*One button to create the document
*One button to create the pdf content
*One button to write the pdf content into the created document
*One button to open the file
*Only Cordova File plugin
And following and adapting the solution in this post:
https://github.com/pwlin/cordova-plugin-file-opener2/issues/60
Later I´ll do a video tutorial because this issue seems to be common and hard to solve.

PDF not working with List Int array passed to Browser

Hi I have a defined variable contentAll from where I am writing to server as a PDF and mailing it to users. They want to see it open in a browser.
Server C# code is as below
List<int> contentAll = new List<int>();
contentAll = [01,02, 03,.....] etc. - Just a sample
byte[] base64EncodedStringBytes = Encoding.ASCII.GetBytes(Convert.ToBase64String(contentAll.SelectMany<int, byte>(BitConverter.GetBytes).ToArray()));
return Ok(base64EncodedStringBytes);
Jquery Code is as below
var pdfWin = window.open("data:application/pdf;base64," + response, "_blank", 'height=650,width=840');
Where response is the returned base64EncodedStringBytes
I am able to write the PDF and send it so no issues with content.
However Chrome is not opening it. The Error in PDF window . Can someone assist

Download PDF file in HTML5/Javascript MOBILE application

I need to create functionality which allows a user to download a PDF file from my HTML5/JavaScript-based mobile application. I will be getting the PDF file as a Base 64 encoded byte stream. How can I allow the user to download the PDF to their device upon clicking a button in the page?
For IOS:
You can download a pdf on iPhone apps and show it in a WebView.
Some ways are listed at this (linked) question. You can also find there how to put the pdf in a folder of the device/iPhone running the app: How to download PDF and store it locally on iPhone?
let request = URLRequest(url: URL(string: "http://www.msy.com.au/Parts/PARTS.pdf")!)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
if error == nil{
if let pdfData = data {
let pathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("\(filename).pdf")
do {
try pdfData.write(to: pathURL, options: .atomic)
}catch{
print("Error while writting")
}
DispatchQueue.main.async {
self.webView.delegate = self
self.webView.scalesPageToFit = true
self.webView.loadRequest(URLRequest(url: pathURL))
}
}
}else{
print(error?.localizedDescription ?? "")
}
}); task.resume()
For Android:
There are many ways to do it for Android. This one should work in most cases without any issue:
URL u = new URL("http://www.path.to/a.pdf");
//open a connection
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File(root,"file.pdf"));
//read the file
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) {
f.write(buffer,0, len1);
}
f.close();
This other one-line option works to download a pdf in android, but seems to have different behavior depending on the device and other installed apps (pdf reader):
`startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("path/filename.pdf")));`
I used this question and it's reply to get a working code example. You can find a long answer at the bottom of the post with many different use-cases and their solutions explained at the same post.: How to download a pdf file in Android?

How to print a PDF from a web page

Does anybody know how to make a print page button print a pdf document?
At the moment i'm using
Print Page
Obviously that just prints the page though. I have had to create pdf's for each page and thought it would be easier just to print the pdf instead of the page (Cross browser printing styles is kinda sucking ;).
Any ideas?
There is no standard way to print anything in PDF in any browser, such as on the Windows platform. On the Mac, there is always an option to print something as a PDF file, so regular printing will do.
I suggest you use Itextsharp. If you are using asp.net c#, this code works for you. Runs in the server side though. You can just put the html inside a panel to make it readable in the server.
/// import these namespaces
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;
using System.Web.Services;
using System.Text;
/// Call this method whenever you need to convert
/// the html content inside the panel which runs in the server side.
[WebMethod]
public void ConvertHtmlStringToPDF()
{
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
pnlPDF.RenderControl(hw);
string htmlDisplayText = sb.ToString();
Document document = new Document();
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
StringReader se = new StringReader(htmlDisplayText);
HTMLWorker obj = new HTMLWorker(document);
document.Open();
obj.Parse(se);
// step 5: we close the document
document.Close();
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=report.pdf");
Response.ContentType = "application/pdf";
Response.Buffer = true;
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.OutputStream.Flush();
Response.End();
}

Categories