Have a little method which goes to the database and retrieves a pdf document from a varbinary column and then adds data to it. I would like to add code so that if this document (company stationery ) is not found then a new blank document is created and returned. The method could either return a Byte[] or a Stream.
Problem is that the variable "bytes" in the else clause is null.
Any ideas what's wrong?
private Byte[] GetBasePDF(Int32 AttachmentID)
{
Byte[] bytes = null;
DataTable dt = ServiceFactory
.GetService().Attachments_Get(AttachmentID, null, null);
if (dt != null && dt.Rows.Count > 0)
{
bytes = (Byte[])dt.Rows[0]["Data"];
}
else
{
// Create a new blank PDF document and return it as Byte[]
ITST.Document doc =
new ITST.Document(ITST.PageSize.A4, 50f, 50f, 25f, 25f);
MemoryStream ms = new MemoryStream();
PdfCopy copy = new PdfCopy(doc, ms);
ms.Position = 0;
bytes = ms.ToArray();
}
return bytes;
}
You are trying to use PdfCopy but that's intended for existing documents, not new ones. You just need to create a "blank" document using PdfWriter and Document. iText won't let you create a 100% empty document but the code below essentially does that by just adding a space.
private static Byte[] CreateEmptyDocument() {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph(" "));
doc.Close();
}
}
return ms.ToArray();
}
}
I think you may need to use
bytes = ms.GetBuffer();
not
bytes = ms.ToArray();
Related
I have searched and I could not find an answer. For example, this doesn't work. My port:
static byte[] RtfToPdf(string rtf)
{
byte[] pdf = null;
using (var inputStream = GenerateStreamFromString(rtf))
using (var outputStream = new MemoryStream())
{
var pdfDocument = new iTextSharpDocument();
var pdfWriter = PdfWriter.GetInstance(pdfDocument, outputStream);
pdfDocument.Open();
RtfParser rtfParser = new RtfParser(null);
rtfParser.ConvertRtfDocument(inputStream, pdfDocument);
pdfDocument.Close();
pdfWriter.Close();
pdf = outputStream.ToArray();
}
return pdf;
}
public static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.UTF8.GetBytes(value));
}
That simply copies the text of the RTF to a PDF without any of the formatting that was in the RTF. I am using iTextSharp-LGPL which is version 4.1.6 of iTextSharp.
I personally can't find any useful documentation. iText itself isn't intuitive so I'm having a hard time even guessing about what to try.
How to merge two pdf files with layers using itextsharp in C#, I tried but losing layers
// step 1: creation of a document-object
Document document = new Document();
// step 2: we create a writer that listens to the document
PdfCopy writer = new PdfCopy(document, new FileStream(outPutFilePath, FileMode.Create));
if(writer == null)
{
return;
}
// step 3: we open the document
document.Open();
foreach(string fileName in filesPath)
{
// we create a reader for a certain document
PdfReader reader = new PdfReader(fileName);
reader.ConsolidateNamedDestinations();
// step 4: we add content
for(int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
page.ContentTagged = true;
writer.AddPage(page);
}
PRAcroForm form = reader.AcroForm;
if(form != null)
{
// writer.CopyDocumentFields(reader);
}
reader.Close();
}
// step 5: we close the document and writer
writer.Close();
document.Close();
The code below is correctly assigning the value "foo" to the named field, but the field is not being "flattened". I must be neglecting a step, but I don't know what it is. Please advise. Thanks.
public byte[] FlattenSpecifiedFormFields(byte[] b, List<string> fieldNames2Flatten)
{
PdfReader reader = new PdfReader(b);
using (var ms = new MemoryStream())
{
var stamper = new iTextSharp.text.pdf.PdfStamper(reader, ms);
foreach (string name in fieldNames2Flatten)
{
stamper.AcroFields.SetField(name, "foo");
stamper.PartialFormFlattening(name);
}
stamper.Close();
return ms.ToArray();
};
}
Even when partially flattening a form, the PdfStamper FormFlattening property must be set to true. I.e.:
var stamper = new PdfStamper(reader, ms);
stamper.FormFlattening = true;
foreach (string name in fieldNames2Flatten)
{
stamper.AcroFields.SetField(name, "foo");
stamper.PartialFormFlattening(name);
}
I'm trying to serialize an XML file between two software components, with a client-server fashioned code.
First of all, i'll show how i solved the same issue for Bitmaps (code has been simplified for writting this):
Initially, this code serializes me Bitmaps at the server side:
public String ImageToString(Bitmap img)
{
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
}
return Convert.ToBase64String(byteArray);
}
And this deserializes the Bitmap at the client side:
public Bitmap StringToImage(string imageString)
{
byte[] array = Convert.FromBase64String(imageString);
Bitmap image = (Bitmap)Bitmap.FromStream(new MemoryStream(array));
return image;
}
What i really want to do now is do the same, but with XML files. I have at the server side:
public XmlDocument RemoteXMLfile()
{
XmlDocument doc = new XmlDocument();
doc.Load("myXMLFile.xml");
return doc;
}
But this makes the compiler to complain because it finds the XML document unmarked as serializable.
My question is: how do i solve this? Thanks!
I answer my own question:
The XMLDocuments is loaded and converted to a byte array at the server side:
public byte[] RemoteXMLfile()
{
XmlDocument doc = new XmlDocument();
doc.Load("myLocalXMLfile.xml");
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
doc.Save(stream);
stream.Close();
byteArray = stream.ToArray();
}
return byteArray;
}
And at the client side, we convert again to an XML document from its byte array shape:
byte[] docbytearray = RemoteXMLfile();
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream(docbytearray);
doc.Load(ms);
I am trying to download and merges multiple pdf files by using ITextSharp.
It used to working before but I being got an "Content can not be added to a PdfImportedPage." error message on the line:
importedPage = writer.GetImportedPage(reader, currentPageIndex);
The full code is below, any help will be very appreciated.
private string MergeDocuments(IList<string> fileUrls, string fileName)
{
var reportFolder = this.ReportFolder + "\\";
using (MemoryStream output = new MemoryStream())
{
Document document = new Document();
try
{
// Initialize pdf writer
PdfWriter writer = PdfWriter.GetInstance(document, output);
// Open document to write
document.Open();
PdfContentByte content = writer.DirectContent;
PdfImportedPage importedPage;
// Iterate through all pdf documents
foreach (var url in fileUrls)
{
// Create pdf reader
using (PdfReader reader = new PdfReader(new Uri(url)))
{
int numberOfPages = reader.NumberOfPages;
// Iterate through all pages
for (int currentPageIndex = 1; currentPageIndex <= numberOfPages; currentPageIndex++)
{
// Determine page size for the current page
document.SetPageSize( reader.GetPageSizeWithRotation(currentPageIndex) );
// Create page
document.NewPage();
importedPage = writer.GetImportedPage(reader, currentPageIndex);
content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
}
}
}
}
catch (Exception exception)
{
throw new Exception("Error occured", exception);
}
File.WriteAllBytes(reportFolder + fileName + ".pdf", output.GetBuffer());
}
return "Reports/" + fileName + ".pdf";
}
When I try the following code, I get a null pointer exception in the addDocument() method:
using (MemoryStream output = new MemoryStream()) {
Document document = new Document();
document.Open();
PdfCopy copy = new PdfSmartCopy(document, output);
foreach (var url in fileUrls) {
using (WebClient client = new WebClient()) {
var byteArray = client.DownloadData(url);
PdfReader reader = new PdfReader(byteArray);
copy.AddDocument(reader);
reader.Close();
}
}
}
I found the problem, the document object should be closed before writing memory stream to file.
Just added document.Close() as below.
document.Close();
File.WriteAllBytes(reportFolder + fileName + ".pdf", output.GetBuffer());