问题
I've got some code for itextsharp merging 2 pdf files. Found it online somewhere. The merging works fine, but it seems that the source files are staying in use after it is all done. What I'd like to do is to delete the first file that i have already merged, which is uploaded via a fileupload, and keep only the merged file. It's definitely the code doing the merging that is causing the file to stay open. I tried to delete the file on the server and it tells me something like it's open by the IIShelper. Through hours of work I narrowed to down to this stuff. Why is it keeping the file in use?
public static void MergeFiles(string destinationFile, string[] sourceFiles)
{
int f = 0;
// we create a reader for a certain document
PdfReader reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
// step 1: creation of a document-object
Document document = new Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
// step 3: we open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
if(reader.IsEncrypted() == false)
{
// step 4: we add content
while (f < sourceFiles.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
f++;
if (f < sourceFiles.Length)
{
reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
n = reader.NumberOfPages;
}
}
}
else
{
//is encrypted
}
// step 5: we close the document
document.Close();
reader.Close();
reader.Dispose();
}
Thanks in advance
回答1:
You are only closing one reader
at the end, but opening one reader per file. Thus, only the last reader
will get closed.
You need to close the old reader before you do
reader = new PdfReader(sourceFiles[f]);
回答2:
Ok, here is what I ended up with.
public static void MergeFiles(string destinationFile, string[] sourceFiles)
{
int f = 0;
// we create a reader for a certain document
//PdfReader reader = new PdfReader(sourceFiles[f]);
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(sourceFiles[f], true), null);
if (reader.IsEncrypted() == false)
{
// we retrieve the total number of pages
int n = reader.NumberOfPages;
// step 1: creation of a document-object
Document document = new Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
using(var destinationFileStream = new FileStream(destinationFile, FileMode.Create))
{
PdfWriter writer = PdfWriter.GetInstance(document, destinationFileStream);
// step 3: we open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
// step 4: we add content
while (f < sourceFiles.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
f++;
if (f < sourceFiles.Length)
{
reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
n = reader.NumberOfPages;
}
}
//close everything
document.Close();
reader.Close();
destinationFileStream.Close();
}
}
else
{
//is encrypted
reader.Close();
}
}
I tried every possible combination of closing the reader, etc.., but it would seem that no matter what itext kept source file open.
What did the trick was changing PdfReader reader = new PdfReader(sourceFiles[f]) to PdfReader reader = new PdfReader(new RandomAccessFileOrArray(sourceFiles[f], true), null).
The RandomAccessFileOrArray made the difference.
I'm not by any means an itextsharp expert. Can someone explain to me why exactly this has such a large effect on itext releasing files in this case?
回答3:
Here is what I did : I created a list of all readers of files I merge to keep track of them, then I closed them all in the end.
List<PdfReader> readers = new List<PdfReader>();
try
{
int f = 0;
//PdfReader reader = new PdfReader(sSrcFile[f]);
readers.Add(new PdfReader(sSrcFile[f]));
int n = readers[f].NumberOfPages;
//Response.Write("There are " + n + " pages in the original file.\n");
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
while (f < sSrcFile.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(PageSize.A4);
document.NewPage();
page = writer.GetImportedPage(readers[f], i);
rotation = readers[f].GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, readers[f].GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
//Response.Write("\n Processed page " + i + "\n");
}
f++;
if (f < sSrcFile.Length)
{
readers.Add(new PdfReader(sSrcFile[f]));
n = readers[f].NumberOfPages;
//Response.Write("ff : There are " + n + " pages in the original file.\n");
}
}
//Response.Write(returnLocation);
document.Close();
for (var i = 0; i < readers.Count; i++)
{
readers[i].Close();
}
return returnLocation;
}
catch (Exception e)
{
Response.Write("The error message is: " + e.Message);
return e.Message;
}
回答4:
I had the same problem in VB.net. You need to close each reader, pdfDoc and writer.
Imports iTextSharp.text.pdf
Imports iTextSharp.text
Public Sub MergePDF_File(ByVal fileArray As String(), ByVal outPutPDF As String)
If fileArray Is Nothing OrElse fileArray.Length = 0 Then
Throw New ApplicationException("No file list")
End If
If String.IsNullOrEmpty(outPutPDF) Then
Throw New ApplicationException("Must specify output file")
End If
Dim pdfDoc As iTextSharp.text.Document = Nothing
Dim writer As iTextSharp.text.pdf.PdfCopy = Nothing
For i = 0 To fileArray.Length - 1
Using reader As New iTextSharp.text.pdf.PdfReader(fileArray(i))
If i = 0 Then
pdfDoc = New iTextSharp.text.Document(reader.GetPageSizeWithRotation(1))
writer = New iTextSharp.text.pdf.PdfCopy(pdfDoc, _
New FileStream(outPutPDF, _
FileMode.OpenOrCreate, _
FileAccess.Write))
pdfDoc.Open()
End If
Dim pageCount As Integer = reader.NumberOfPages
For pg = 1 To pageCount
pdfDoc.SetPageSize(reader.GetPageSizeWithRotation(pg))
pdfDoc.NewPage()
Dim page As iTextSharp.text.pdf.PdfImportedPage = Nothing
page = writer.GetImportedPage(reader, pg)
writer.AddPage(page)
Next
reader.Close()
End Using
Next
pdfDoc.Close()
writer.Close()
End Sub
回答5:
One thing I noticed is that you are not closing out the FileStream object that you are constructing. Since the FileStream class implements IDisposable, I would highly recommend that you wrap the code in a using block so that the resources will be cleaned up appropriately.
using(var destinationFileStream = new FileStream(destinationFile, FileMode.Create))
{
PdfWriter writer = PdfWriter.GetInstance(document, destinationFileStream));
// step 3: we open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
if(reader.IsEncrypted() == false)
{
// step 4: we add content
while (f < sourceFiles.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
f++;
if (f < sourceFiles.Length)
{
reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
n = reader.NumberOfPages;
}
}
}
else
{
//is encrypted
}
}
来源:https://stackoverflow.com/questions/20574993/itextsharp-not-closing-files