【问题标题】:IText 7 in C# locking bad pdfC#中的IText 7锁定坏pdf
【发布时间】:2021-07-05 13:42:30
【问题描述】:

我在使用 IText 7 检查用户从互联网上下载的 PDF 时遇到了问题。

对于我的测试用例,我创建了一个包含垃圾的文本文件并将其保存为 pdf。我知道它无效。

在代码中,我尝试使用 PDFReader 打开 PDF。

抛出异常,这是意料之中的。 在调试代码时,Reader 对象在到达 finally 点时为空。所以 reader.close() 甚至没有触发。 我什至将文件复制到临时目录只是为了确保没有其他文件保存该文件。

出现异常后,我无法在代码中或在文件资源管理器中手动删除 PDF 文件。 这是我的一些代码。我删除了除阅读器部分之外的所有内容。此外,这段代码是在我尝试了一些事情之后,所以你看到我尝试将文件复制到临时文件。我试图在最后部分删除临时文件。这在损坏的文件上失败。

以下是尝试验证错误 PDF 时引发的两个异常。第一个来自 PDFReader 调用。

2021-04-09 13:18:11,079 错误 GUI.Form1 - 找不到 PDF 标题。
iText.IO.IOException:找不到 PDF 标头。在
iText.IO.Source.PdfTokenizer.GetHeaderOffset() 在
iText.Kernel.Pdf.PdfReader.GetOffsetTokeniser(IRandomAccessSource> byteSource) at
iText.Kernel.Pdf.PdfReader..ctor(字符串文件名,ReaderProperties 属性)在
iText.Kernel.Pdf.PdfReader..ctor(FileInfo 文件) at
GUI.Form1.validatePDF(FileInfo pdfFile, HashSet`1 tmpMd5s)

第二个是尝试删除临时文件

2021-04-09 13:18:11,116 错误 GUI.Form1 - 进程无法访问文件
'C:\Users\ret63\AppData\Local\Temp\tmp27DE.tmp' 因为它正被另一个进程使用。
System.IO.IOException:该进程无法访问文件“C:\Users\ret63\AppData\Local\Temp\tmp27DE.tmp”,因为它正被另一个进程使用。在
System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileInfo.Delete() at
GUI.Form1.validatePDF(FileInfo pdfFile, HashSet`1 tmpMd5s)

PdfDocument pdfDoc = null;
PdfReader reader = null;

try
{
    using (reader = new PdfReader(testFile))
    {
        //pdfDoc = new PdfDocument(reader);
        //pdfDoc = new PdfDocument(new PdfReader(pdfFile.FullName));
        //Console.WriteLine("Number of Pages: " + pdfDoc.GetNumberOfPages());
        //pdfDoc.Close();
    }
}
catch(Exception ex)
{
    log.Error(ex.Message, ex);
    throw new Exception("Invalid PDF File: " + pdfFile.Name);
}
finally
{
    if (reader != null)
    {
        reader.Close();
    }
    if (pdfDoc != null && !pdfDoc.IsClosed())
    {
        pdfDoc.Close();
    }

    try
    {
        if (testFile.Exists)
        {
            testFile.Delete();
        }
    }
    catch (Exception ee)
    {
        Console.WriteLine(ee.Message);
    }
}

【问题讨论】:

  • 如果new PdfReader(testFile) 抛出异常,reader 的赋值将永远不会发生,这就解释了为什么它为空。你不必担心这一点。如果PdfReader 构造函数在抛出异常之前打开了任何资源,它负责关闭它们。
  • 好的,但是如果 PDFReader 对象为空,为什么阅读器中的文件会被锁定?阅读器调用是锁定文件的原因,因为如果我做同样的事情但调用 PDFReader,它不会被锁定
  • 这是您问题中有趣的部分。能否包含来自ee 的错误消息?
  • 我更新了原来的帖子,但有例外。

标签: c# itext


【解决方案1】:

看起来像一个 iText 错误。如果您追踪PdfReader 构造函数调用的内容,您会看到它creates a FileStream 被条件锁定。 FileStream 被包裹在 RandomAccessSource 中,然后在 GetOffsetTokeniser 中被包裹在 PdfTokenizer 中。如果 GetHeaderOffset 在第 1433 行抛出,则 tok local 永远不会关闭。

【讨论】:

  • 我也是这么想的。我目前忽略了这个问题,并将损坏的文件留在了临时文件夹中。我会考虑要求 IText 检查错误。
  • @EricT 您可以使用带有Stream 的构造函数并自己关闭它。
  • 使用流有效.. 感谢您的建议。
  • 这应该是fixed in develop。该修复将包含在下一个版本中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 2022-01-19
  • 1970-01-01
  • 2014-03-24
  • 2017-09-17
相关资源
最近更新 更多