我正在尝试获取所有图片pdf并在该图片上方写下一些文字。我正在使用以下代码,但收到错误"无法访问已关闭的文件"
private static void InsertTextToPdf(string sourceFileName, string newFileName)
{
var img = new ReadPDFContent.ImagePDF.MyImageRenderListener();
using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
{
PdfReader pdfReader = new PdfReader(pdfStream);
PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
pdfContentByte.SetColorFill(BaseColor.BLUE);
pdfContentByte.SetFontAndSize(baseFont, 8);
pdfContentByte.BeginText();
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, " ", 400, 600, 0);
Dictionary<string, System.Drawing.Image> images;
images = new Dictionary<string, System.Drawing.Image>();
using (var reader = new PdfReader(sourceFileName))
{
var parser = new iTextSharp.text.pdf.parser.PdfReaderContentParser(reader);
ImageRenderListener listener = null;
for (var i = 1; i <= reader.NumberOfPages; i++)
{
parser.ProcessContent(i, (listener = new ImageRenderListener()));
var index = 1;
if (listener.Images.Count > 0)
{
try
{
var image = iTextSharp.text.Image.GetInstance(pdfStream);
float xval = image.AbsoluteX;
float yval = image.AbsoluteY;
image.SetAbsolutePosition(xval, yval);
pdfContentByte.ShowText("rahul");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
pdfContentByte.EndText();
pdfStamper.Close();
}
}
错误发生在以下行:
iTextSharp.text.Image.GetInstance(pdfStream);
并且在调试我发现实际文件读取时,在pdfreader读取流后seeek被设置为false。
答案 0 :(得分:3)
这很简单:只要从PdfReader
构造Stream
,该流就会在读到结束后关闭。因此,在
PdfReader pdfReader = new PdfReader(pdfStream);
pdfStream
已关闭。
是的,这与源代码注释相矛盾,该注释声称“流被读取到最后但未关闭”:
/**
* Reads and parses a PDF document.
* @param isp the <CODE>InputStream</CODE> containing the document. The stream is read to the
* end but is not closed
* @throws IOException on error
*/
public PdfReader(Stream isp) : this(isp, null) {
}
/**
* Reads and parses a PDF document.
* @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
* end but is not closed
* @param ownerPassword the password to read the document
* @throws IOException on error
*/
public PdfReader(Stream isp, byte[] ownerPassword) : this(
new RandomAccessSourceFactory().CreateSource(isp),
false,
ownerPassword,
null,
null,
false) {
}
但是看一下使用过的RandomAccessSourceFactory
方法CreateSource
重载:
/**
* Creates a {@link RandomAccessSource} based on an {@link InputStream}. The full content of the InputStream is read into memory and used
* as the source for the {@link RandomAccessSource}
* @param is the stream to read from
* @return the newly created {@link RandomAccessSource}
*/
public IRandomAccessSource CreateSource(Stream inp) {
try {
return CreateSource(StreamUtil.InputStreamToArray(inp));
}
finally {
try {inp.Close();}catch{}
}
}
即。强制执行Close
。
话虽如此,如果文件没有关闭,你只会有一个不同的例外。
在
PdfReader pdfReader = new PdfReader(pdfStream);
将流读到最后,所以这里
var image = iTextSharp.text.Image.GetInstance(pdfStream);
没有什么可以从流中读取。
即使您确实将流重置为Image.GetInstance
之前的开头,您还会遇到另一个例外:流内容是PDF或位图图像。如果是PDF,Image.GetInstance
将失败;如果是位图,new PdfReader
将失败(假设您没有使用其中一个构造文件,这些文件都被接受为位图,并通过网格格式化为PDF)
关于在文件中的图像上方写入一些文本的任务,您可以通过创建自定义渲染侦听器(而不是使用忽略图像坐标的现有渲染器)来完成此操作,例如:像这样:
public class ImageEntitlingRenderListener : IRenderListener
{
BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
PdfStamper pdfStamper = null;
int page = 0;
public ImageEntitlingRenderListener(PdfStamper pdfStamper, int page)
{
this.pdfStamper = pdfStamper;
this.page = page;
}
public void RenderImage(ImageRenderInfo renderInfo)
{
Matrix ctm = renderInfo.GetImageCTM();
float xCenter = ctm[Matrix.I31] + 0.5F * ctm[Matrix.I11];
float yTop = ctm[Matrix.I32] + ctm[Matrix.I22];
PdfContentByte pdfContentByte = pdfStamper.GetOverContent(page);
pdfContentByte.SetColorFill(BaseColor.BLUE);
pdfContentByte.SetFontAndSize(baseFont, 8);
pdfContentByte.BeginText();
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "rahul", xCenter, yTop, 0);
pdfContentByte.EndText();
}
public void BeginTextBlock() { }
public void EndTextBlock() { }
public void RenderText(TextRenderInfo renderInfo) { }
}
你可以像这样使用它:
private static void InsertTextToPdf(string sourceFileName, string newFileName)
{
using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
{
PdfReader pdfReader = new PdfReader(pdfStream);
PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
var parser = new PdfReaderContentParser(pdfReader);
for (var i = 1; i <= pdfReader.NumberOfPages; i++)
{
parser.ProcessContent(i, (new ImageEntitlingRenderListener(pdfStamper, i)));
}
pdfStamper.Close();
pdfReader.Close();
}
}
请注意,代码中有一些简化的假设。特别是它假定图像在PDF中直立绘制。您可能希望改进代码以获得更通用的用途。