I am using Microsoft API Graph API to get a PDF file from my OneDrive which I have successfully got via this line:
var streamFile = await graphClient.Me.Drive.Items["{item-id}"].Content.Request().GetAsync();
Now I want to take a the stream of this file and edit it with iTextSharp
using (MemoryStream outFile = new MemoryStream())
{
//Dont know what to replace this with
PdfReader pdfReader = new PdfReader("Uploads/Document.pdf");
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
AcroFields fields = pdfStamper.AcroFields;
fields.SetField("Full_Names", "aaa");
pdfStamper.Close();
pdfReader.Close();
}
And then upload it back to OneDrive, which I am able to do via this:
//Don't know what to replace this with
var uploadPath = System.Web.HttpContext.Current.Server.MapPath("~/Uploads/NewDocument.pdf");
byte[] data = System.IO.File.ReadAllBytes(uploadPath);
Stream stream = new MemoryStream(data);
await graphClient.Me.Drive.Items["{item-id}"].ItemWithPath("NewDocument.pdf").Content.Request().PutAsync<DriveItem>(stream);
So my question is how do I take my file that I got and use iTextSharp to do its thing? So I can upload this new edited file?
UPDATE
I tried this:
var streamFile = await graphClient.Me.Drive.Items["{item-id}"].Content.Request().GetAsync();
using (MemoryStream outFile = new MemoryStream())
{
PdfReader pdfReader = new PdfReader(streamFile);
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
AcroFields fields = pdfStamper.AcroFields;
fields.SetField("Full_Names", "JIMMMMMMAYYYYY");
await graphClient.Me.Drive.Items["{item-id}"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(outFile);
pdfStamper.Close();
pdfReader.Close();
}
But got this error:
Cannot access a closed Stream.
I can see the file is being uploaded to my OneDrive, but when I goto open it I get this error:
Failed to load PDF document.
What am I doing wrong here?
UPDATE
When I remove these last two lines:
pdfStamper.Close();
pdfReader.Close();
I don't get Cannot access a closed Stream error anymore, my file uploads but I get an error when I open it:
Failed to load PDF document.
UPDATE
When I try this
var streamFile = await graphClient.Me.Drive.Items["{item-id}"].Content.Request().GetAsync();
await graphClient.Me.Drive.Items["{item-id}"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(streamFile);
It uploads the file I grabbed, so that part is working, but I can't edit it with iTextSharp.
See if this helps you along:
Do I need to reset a stream(C#) back to the start?
Once you read a stream, you need to reset it back to the beginning to do something else with it.
Related
I am having a issue where I write to a pdf file and then close it and later on open it up again and try to read it.
I get "Cannot Open .pdf because it is being used by another process?"
var path = // get path
Directory.CrateDirctory(path);
using(var writer = new PdfWriter(path, //writer properties)){
var reader = new PdfReader(//template);
var pdfDoc = new PdfDcoument(reader, writer);
writer.SetCloseStream(false)
// some code to fill in the pdf
reader.Close();
pdfDoc.Close();
}
//later in code
using(var stream = new MemoryStream(File.ReadAllBytes(//the file that I crated above)))
{
// do some stuff here
}
I get the error right on the using statement above. I thought all the streams for creating the pdf are closed at this point but it seems like it is not.
The issue is with the line writer.SetCloseStream(false);. That is telling it to not close the stream when the writer is closed. Since the stream is left open you will get an IOException when you create another stream for reading. Remove this line or set to true to resolve the issue.
If you need to keep the stream open for whatever reason, like issues with flushing the write buffer too soon when PdfWriter is closed. Then you can get access to the write stream and close it later when you are ready to read it. Something like this:
Stream outputStream;
using (var writer = new PdfWriter(path)){
writer.SetCloseStream(false);
// do whatever you need here
outputStream = writer.GetOutputStream();
}
// do whatever else you need here
// close the stream before creating a read stream
if(null != outputStream) {
outputStream.Close();
}
using (var stream = new MemoryStream(File.ReadAllBytes(path)))
{
// do some stuff here
}
I have been struggling with this issue for days now and cant find a solution anywhere, The only thing I can think of is that iTextSharp doesn't work....
First I create a MemoryStream like so:
MemoryStream outFile = new MemoryStream();
I have this Stream here:
var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();
Which is a PDF file from Microsoft OneDrive
Then I take this Stream and assign it to iTextSharp's PdfReader like so:
PdfReader pdfReader = new PdfReader(streamFile);
Then I use PDFStamper to make edits to the PDF File like so:
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
Then I do my edits like so:
AcroFields fields = pdfStamper.AcroFields;
fields.SetField("Full_Names", "JIMMMMMMAYYYYY");
Then I re-upload the file to OneDrive (which is also expecting a Stream) like so:
await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync(outFile);
But I get this error:
Cannot access a closed Stream.
on this line:
await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(outFile);
When I just get my file from OneDrive and Upload it like so:
var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();
await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(streamFile);
It works! I am able to get the file and re-upload it, so its not an issue with the PDF file at all, iTextSharp is broken I have tried multiple things and nothing works at all. What is iTextSharp doing wrong? Here is my full code:
using (MemoryStream outFile = new MemoryStream())
{
var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();
using (PdfReader pdfReader = new PdfReader(streamFile))
{
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile))
{
AcroFields fields = pdfStamper.AcroFields;
fields.SetField("Full_Names", "JIMMMMMMAYYYYY");
}
}
await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(outFile);
}
What the hell is going wrong?
The stamper closes the inner stream when it gets disposed. Add this line just below the line where you create the stamper:
pdfStamper.Writer.CloseStream = false;
I have an MVC application that is uploading a PDF file and rendering each page as single PNG image using Magick.NET. The conversion is fine in most cases, but in some I am getting a blank image where text should be and other lines of text displaying correctly in the same image. Does anyone know what could be causing this?
Below is the code I'm using.
public FileResult PNGPreview(Guid id, Int32 index)
{
MagickReadSettings settings = new MagickReadSettings();
// Settings the density to 300 dpi will create an image with a better quality
settings.FrameIndex = index;
settings.FrameCount = 1;
settings.Density = new PointD(300, 300);
settings.UseMonochrome = true;
using (MagickImageCollection images = new MagickImageCollection())
{
// Add all the pages of the pdf file to the collection
images.Read(CreateDocument(id), settings);
using (MemoryStream stream = new MemoryStream())
{
images[0].Write(stream, MagickFormat.Png24);
stream.Close();
byte[] result = stream.ToArray();
return File(result, "image/png");
}
}
}
private byte[] CreateDocument(Guid id)
{
PdfReader reader = new PdfReader(Server.MapPath(String.Format("~/documenttemplates/{0}.pdf", id)));
byte[] result = null;
using (MemoryStream ms = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(reader, ms, '\0', false);
stamper.Close();
reader.Close();
result = ms.ToArray();
}
return result;
}
The PDF file that caused this issue was provided to me by e-mail and I was told that this file was created with Word and then edited with Foxit Pro.
Magick.NET uses Ghostscript to convert the PDF file to an image. A command similar to the one below is executed.
"c:\Program Files (x86)\gs\gs9.16\bin\gswin32c.exe" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE
-dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 -sDEVICE=pnggray"
-dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r72x72" "-sOutputFile=Test.%d.png" "-fTest.pdf"
And that will tell us that the file that was created is corrupt.
**** Error reading a content stream. The page may be incomplete.
**** File did not complete the page properly and may be damaged.
**** Error reading a content stream. The page may be incomplete.
**** File did not complete the page properly and may be damaged.
**** This file had errors that were repaired or ignored.
**** The file was produced by:
**** >>>> Microsoft? Word 2013 <<<<
**** Please notify the author of the software that produced this
**** file that it does not conform to Adobe's published PDF
**** specification.
This can be solved by creating the input file with a different program.
I'm developing an ASP.NET application where I have to send an PDF based on a Table created dinamically on the page as attachment on a email. So I have a function that creates the PDF as iTextSharp Document and returns it. If i try just to save this document, it works fine but I'm having a bad time trying to make it as Stream. I tried several things already, but I always get stuck at some point.
I tried to serialize it, but appears that Document is not serializable. Then I tried to work with PdfCopy, but I couldn't find out how to use this to my problem in specific.
The code right now is like this:
//Table,string,string,Stream
//This document returns fine
Document document = Utils.GeneratePDF(table, lastBook, lastDate, Response.OutputStream);
using (MemoryStream ms = new MemoryStream())
{
PdfCopy copy = new PdfCopy(document, ms);
//Need something here to copy from one to another! OR to make document as Stream
ms.Position = 0;
//Email, Subject, Stream
Utils.SendMail(email, lastBook + " - " + lastDate, ms);
}
Try to avoid passing the native iTextSharp objects around. Either pass streams, files or bytes. I don't have an IDE in front of me right now but you should be able to do something like this:
byte[] Bytes;
using(MemoryStream ms = new MemoryStream()){
Utils.GeneratePDF(table, lastBook, lastDate, ms);
Bytes = ms.ToArray();
}
Then you can either change your Utils.SendMail() to accept a byte array or just wrap it in another stream.
EDIT
You might also be able to just do something like this in your code:
using(MemoryStream ms = new MemoryStream()){
Utils.GeneratePDF(table, lastBook, lastDate, ms);
ms.Position = 0;
Utils.SendMail(email, lastBook + " - " + lastDate, ms);
}
I did this in the past by doing something like the following:
using (Document doc = new Document())
{
MemoryStream msPDFData = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, msPDFData);
doc.Open();
doc.Add(new Paragraph("I'm a pdf!");
}
If you need access to the raw data you can also do
byte[] pdfData = msPDFData.ToArray();
I need to add a user's signature (like your signature on a credit card, for example) to a PDF document online. How can I do it? What is the best practice for this kind of tasks?
You can use iTextSharp to do it. Something like this will work for you:
PdfReader pdfReader = null;
PdfStamper pdfStamper = null;
// Open the PDF file to be signed
pdfReader = new PdfReader(this.signFile.FullName);
// Output stream to write the stamped PDF to
using (FileStream outStream = new FileStream(targetFilename, FileMode.Create))
{
try
{
// Stamper to stamp the PDF with a signature
pdfStamper = new PdfStamper(pdfReader, outStream);
// Load signature image
iTextSharp.text.Image sigImg = iTextSharp.text.Image.GetInstance(SIGNATURE_IMAGE_PATH);
// Scale image to fit
sigImg.ScaleToFit(MAX_WIDTH, MAX_HEIGHT);
// Set signature position on page
sigImg.SetAbsolutePosition(POS_X, POS_X);
// Add signatures to desired page
PdfContentByte over = pdfStamper.GetOverContent(PAGE_NUM_TO_SIGN);
over.AddImage(sigImg);
}
finally
{
// Clean up
if (pdfStamper != null)
pdfStamper.Close();
if (pdfReader != null)
pdfReader.Close();
}
}
You need to implement some action with JavaScript. You can use some JQuery pluging for that. Here is an example;
http://motyar.blogspot.com/2010/01/draw-with-jquery.html
For the pdf part, you can use some pdf converter tool Like ITextSharp