I'm trying to save to databse a pdf file generated by itextsharp. But, I haven't been successfully so far.
I'm using Linq to sql.
Here's the code:
MemoryStream ms = new MemoryStream();
Document d = new Document(PageSize.A4, 60, 60, 40, 40);
PdfWriter w = PdfWriter.GetInstance(d, ms);
w.CloseStream = false;
string txtTemplate = "";
Encoding en = Encoding.GetEncoding("iso-8859-1");
StreamReader sr = new StreamReader(HttpContext.Current.Server.MapPath("~/Content/templates/CessaoDireitosDica.txt"), en);
txtTemplate = sr.ReadToEnd();
sr.Close();
string conselhos = "";
Font font = new Font(Font.HELVETICA, 11, Font.NORMAL);
font.SetColor(0xC6, 0xC6, 0xC6);
Paragraph txtBody = new Paragraph(txtTemplate, font);
txtBody .SetAlignment(ElementTags.ALIGN_JUSTIFIED);
d.Open();
d.Add(txtBody);
d.Close();
byte[] pdfDone = ms.ToArray();
w.Flush();
ms.Flush();
ms.Close();
return pdfDone;
It throws no error, but it doesn't save nothing in DB. The DB field is an "image" field type.
I also use this code to render a pdf on the fly (I cut off the byte[] pdfDone... and return the MemoryStream).
I don't know what can be wrong... And debugging, I could also see that byte[] pdfDone has a value (something like 3487), but nothing is saved to DB.
Thanks in advance!
function byte[] CreatePdf(){
byte[] result;
using (MemoryStream ms = new MemoryStream())
{
Document pDoc = new Document(PageSize.A4, 0, 0, 0, 0);
PdfWriter writer = PdfWriter.GetInstance(pDoc, ms);
pDoc.Open();
//here you can create your own pdf.
pDoc.Close();
result = ms.GetBuffer();
}
return result;
}
Related
Help please. I'm trying to get a "deferred" digital signature and embed it in a PDF document. On the server (.net core 3.1) I create a test pdf and add an empty container for the signature. To do this, I use the iTextSharp package (version 5.5.13.3):
public static byte[] GetPdfBytesToSign(byte[] unsignedPdf, string signatureFieldName)
{
//unsignedPdf - source PDF
using (PdfReader reader = new PdfReader(unsignedPdf))
{
//looking for existing signatures
int existingSignaturesNumber = reader.AcroFields.GetSignatureNames().Count;
using (MemoryStream tempPdf = new MemoryStream())
{
//add an empty container for a new signature
using (PdfStamper st = PdfStamper.CreateSignature(reader, tempPdf, '\0', null, true))
{
PdfSignatureAppearance appearance = st.SignatureAppearance;
appearance.SetVisibleSignature(new Rectangle(205, 700, 390, 800), reader.NumberOfPages,
//set the name of the field, it will be needed later to insert a signature
$"{signatureFieldName}{existingSignaturesNumber + 1}");
ExternalBlankSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, BufferSize);
//get a stream that contains the sequence we want to sign
using (Stream contentStream = appearance.GetRangeStream())
{
MemoryStream memoryStream = new MemoryStream();
contentStream.CopyTo(memoryStream);
byte[] bytesToSign = memoryStream.ToArray();
return bytesToSign;
}
}
}
}
}
And here is the problem!!! For some reason, iText can't read the PDF it created with an empty signature container (to embed the received signature from the client).
public static byte[] GetSignedPdf(byte[] unsignedPdfWithContainer, byte[] signature)
{
using var pdfReader = new PdfReader(unsignedPdfWithContainer);//<--throwing an exception here
using var output = new MemoryStream();
var external = new MyExternalSignatureContainer(signature);
MakeSignature.SignDeferred(pdfReader, SignatureFieldName, output, external);
return output.ToArray();
}
I am getting the following exception:
iTextSharp.text.exceptions.InvalidPdfException: "Unexpected '>>' at file pointer 1432"
Test(source) pdf is created like this:
public static byte[] CreatePdf()
{
using (MemoryStream ms = new MemoryStream())
{
Document document = new Document(PageSize.A4, 25, 25, 30, 30);
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
document.Add(new Paragraph("Hello World!"));
document.Close();
writer.Close();
return ms.ToArray();
}
}
I have a controller with the get method and when accessing this controller I need to enter some data from the existing pdf file (template) to return this file. When I return this pdf file to the request, I get an error:
ObjectDisposedException: Cannot access a closed Stream
PdfReader reader = new PdfReader(templateFilePath);
Rectangle rect = reader.GetPageSize(1);
var fs = new MemoryStream();
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
// modify the pdf content
PdfContentByte cb = stamper.GetOverContent(1);
cb.SetColorStroke(iTextSharp.text.BaseColor.GREEN);
cb.SetLineWidth(5f);
cb.Circle(rect.GetLeft(1) + 30, rect.GetBottom(1) + 30, 20f);
cb.Stroke();
}
reader.Close();
fs.Position = 0;
return File(fs, "application/pdf", "newFile");
var reader = new PdfReader(templatePath);
var ms = new MemoryStream();
var pageSize = reader.GetPageSize(1);
byte[] bytes;
using (var stamper = new PdfStamper(reader, ms))
{
var canvas = stamper.GetOverContent(1);
var bf = BaseFont.CreateFont(fontPath, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
//Date
canvas.BeginText();
canvas.SetFontAndSize(bf, 10);
canvas.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
$"10/30/2018",
pageSize.GetRight(Utilities.MillimetersToPoints(26)),
pageSize.GetTop(Utilities.MillimetersToPoints(20.
canvas.EndText();
stamper.Close();
bytes = ms.ToArray();
}
return File(bytes, "application/pdf", "payment.pdf");
I'm adding an image to a iTextSharp pdf in this way:
iTextSharp.text.Document doc = new iTextSharp.text.Document(PageSize.A4, 0F,0F, 0F, 0F);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance("https://s3-eu-west-1.amazonaws.com/foo/bar.png");
img.ScaleToFit(595, 120);
MemoryStream ms = new MemoryStream();
PdfWriter.GetInstance(doc, ms);
doc.Open();
doc.Add(img);
doc.Close();
Then I convert it to byte[] and then to base64 string, so it can be handled by AWS API Gateway.
byte[] pdf = ms.ToArray();
var headersDic = new Dictionary<string, string>();
headersDic.Add("Content-type", "application/pdf");
headersDic.Add("Content-disposition", "inline;filename=file.pdf");
return new APIGatewayProxyResponse
{
Body = Convert.ToBase64String(pdf),
IsBase64Encoded = true,
Headers = headersDic,
StatusCode = 200
};
But the image is not shown in the pdf, just an almost indistinguishable part of it, which is the line you can see here:
Any ideas? maybe the conversions to byte[] or base64 and to binary again are giving problems?
When I add text everything goes good.
Is it possible to add encryption to a PDF dynamically created from multiple MemoryStreams?
Following on from my last question C# Append PDF file to MemoryStream - Cannot access a closed Stream I am trying to add PDF encryption.
From the example I have provided below, if the line pdfStamper.Close(); is commented out I do not get the error Cannot access a closed Stream, but nor is the encryption applied to the generated PDF.
Can somebody please advise as to where I am going wrong and if possible how to achieve a solution to my problem?
public MemoryStream CreateMemoryStream()
{
byte[] dynamicPdfBytes;
using (var dynamicPDfMemoryStream = new MemoryStream())
{
using (var document = new Document(PageSize.A4, 25, 25, 30, 30))
{
PdfWriter.GetInstance(document, dynamicPDfMemoryStream);
document.Open();
var pdfPTable = new PdfPTable(1)
{
TotalWidth = _totalWidth,
LockedWidth = true,
SpacingBefore = _spacingBefore,
SpacingAfter = _spacingAfter
};
float[] widths = { 272f };
pdfPTable.SetWidths(widths);
var image = Image.GetInstance(HttpContext.Current.Server.MapPath("/Images/logo.png"));
image.ScaleToFit(125f, 125f);
image.Alignment = Image.RIGHT_ALIGN;
var pdfPCell = new PdfPCell(image)
{
Border = 0,
HorizontalAlignment = Element.ALIGN_RIGHT
};
pdfPTable.AddCell(pdfPCell);
document.Add(pdfPTable);
}
dynamicPdfBytes = dynamicPDfMemoryStream.ToArray();
}
byte[] pdfBytes;
using (var pdfReader = new PdfReader(HttpContext.Current.Server.MapPath("/Documents/Test.pdf")))
{
using (var pdfMemoryStream = new MemoryStream())
{
var pdfStamper = new PdfStamper(pdfReader, pdfMemoryStream);
var acroFields = pdfStamper.AcroFields;
acroFields.SetField("TestField", "This is a test");
pdfStamper.FormFlattening = true;
pdfStamper.Close();
pdfBytes = pdfMemoryStream.ToArray();
}
}
var files = new List<byte[]> { dynamicPdfBytes, pdfBytes };
byte[] array;
using (var arrayMemoryStream = new MemoryStream())
{
var document = new Document(PageSize.A4, 25, 25, 30, 30);
var pdfWriter = PdfWriter.GetInstance(document, arrayMemoryStream);
document.Open();
var directContent = pdfWriter.DirectContent;
foreach (var bytes in files)
{
var pdfReader = new PdfReader(bytes);
var pdfStamper = new PdfStamper(pdfReader, arrayMemoryStream);
pdfStamper.SetEncryption(null, _password, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
var numberOfPages = pdfReader.NumberOfPages;
for (var i = 1; i <= numberOfPages; i++)
{
document.NewPage();
var page = pdfWriter.GetImportedPage(pdfReader, i);
directContent.AddTemplate(page, 0, 0);
}
pdfStamper.FormFlattening = true;
pdfStamper.Close();
}
document.Close();
array = arrayMemoryStream.ToArray();
}
var memoryStream = new MemoryStream();
memoryStream.Write(array, 0, array.Length);
memoryStream.Position = 0;
return memoryStream;
}
Any assistance would be much appreciated :-)
This may not be the most elegant of solutions, however it is a solution to this specific issue and I hope it proves useful to others.
The following code can be used in conjunction with the original sample code, simply comment out all pdfStamper references in the code above:
private MemoryStream SecureMemoryStream()
{
var memoryStream = CreateMemoryStream();
return GetSecureMemoryStream(memoryStream);
}
private MemoryStream GetSecureMemoryStream(MemoryStream memoryStream)
{
byte[] array;
using (var secureMemoryStream = new MemoryStream())
{
var pdfReader = new PdfReader(memoryStream);
using (var pdfStamper = new PdfStamper(pdfReader, secureMemoryStream))
{
pdfStamper.SetEncryption(null, _password, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
pdfStamper.FormFlattening = true;
}
array = secureMemoryStream.ToArray();
}
var outputStream = new MemoryStream();
outputStream.Write(array, 0, array.Length);
outputStream.Position = 0;
return outputStream;
}
I want to write serial number on a pdf document.
And I achieved it with below code with using itextSharp.dll.
public byte[] Sign(string path, string serialnumber)
{
PdfReader pdfReader = new PdfReader(path);
MemoryStream memoryStream = new MemoryStream();
PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream);
//iterate through all pages in source pdf
for (int pageIndex = 1; pageIndex <= pdfReader.NumberOfPages; pageIndex++)
{
iTextSharp.text.Rectangle pageRectangle = pdfReader.GetPageSizeWithRotation(pageIndex);
PdfContentByte pdfData = pdfStamper.GetUnderContent(pageIndex);
pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 40);
PdfGState graphicsState = new PdfGState();
graphicsState.FillOpacity = 0.4F;
pdfData.SetGState(graphicsState);
pdfData.SetColorFill(iTextSharp.text.Color.BLUE);
pdfData.BeginText();
pdfData.ShowTextAligned(iTextSharp.text.Element.ALIGN_CENTER, serialnumber, pageRectangle.Width - 175, pageRectangle.Height - 50, 0);
pdfData.EndText();
}
pdfStamper.Close();
memoryStream.Close();
return memoryStream.ToArray();
}
But I save pdf documents in database which type is varbinary(max).
So how can I write a number on a document which is saved as binary in database?
As #mkl mentioned, one of the other parameters of PdfReader is byte[], so one can easily use binary data.