因此,我们有一些非常低效的代码,可以根据允许的最大大小将pdf拆分为更小的块。阿卡。如果最大大小为10megs,则会跳过8 meg文件,而16 meg文件将根据页数进行拆分。
这是我继承的代码,并且觉得必须有一种更有效的方法来执行此操作,只需要一个方法,而不需要实例化对象。
我们使用以下代码调用方法:
List<int> splitPoints = null;
List<byte[]> documents = null;
splitPoints = this.GetPDFSplitPoints(currentDocument, maxSize);
documents = this.SplitPDF(currentDocument, maxSize, splitPoints);
方法:
private List<int> GetPDFSplitPoints(IClaimDocument currentDocument, int maxSize)
{
List<int> splitPoints = new List<int>();
PdfReader reader = null;
Document document = null;
int pagesRemaining = currentDocument.Pages;
while (pagesRemaining > 0)
{
reader = new PdfReader(currentDocument.Data);
document = new Document(reader.GetPageSizeWithRotation(1));
using (MemoryStream ms = new MemoryStream())
{
PdfCopy copy = new PdfCopy(document, ms);
PdfImportedPage page = null;
document.Open();
//Add pages until we run out from the original
for (int i = 0; i < currentDocument.Pages; i++)
{
int currentPage = currentDocument.Pages - (pagesRemaining - 1);
if (pagesRemaining == 0)
{
//The whole document has bee traversed
break;
}
page = copy.GetImportedPage(reader, currentPage);
copy.AddPage(page);
//If the current collection of pages exceeds the maximum size, we save off the index and start again
if (copy.CurrentDocumentSize > maxSize)
{
if (i == 0)
{
//One page is greater than the maximum size
throw new Exception("one page is greater than the maximum size and cannot be processed");
}
//We have gone one page too far, save this split index
splitPoints.Add(currentDocument.Pages - (pagesRemaining - 1));
break;
}
else
{
pagesRemaining--;
}
}
page = null;
document.Close();
document.Dispose();
copy.Close();
copy.Dispose();
copy = null;
}
}
if (reader != null)
{
reader.Close();
reader = null;
}
document = null;
return splitPoints;
}
private List<byte[]> SplitPDF(IClaimDocument currentDocument, int maxSize, List<int> splitPoints)
{
var documents = new List<byte[]>();
PdfReader reader = null;
Document document = null;
MemoryStream fs = null;
int pagesRemaining = currentDocument.Pages;
while (pagesRemaining > 0)
{
reader = new PdfReader(currentDocument.Data);
document = new Document(reader.GetPageSizeWithRotation(1));
fs = new MemoryStream();
PdfCopy copy = new PdfCopy(document, fs);
PdfImportedPage page = null;
document.Open();
//Add pages until we run out from the original
for (int i = 0; i <= currentDocument.Pages; i++)
{
int currentPage = currentDocument.Pages - (pagesRemaining - 1);
if (pagesRemaining == 0)
{
//We have traversed all pages
//The call to copy.Close() MUST come before using fs.ToArray() because copy.Close() finalizes the document
fs.Flush();
copy.Close();
documents.Add(fs.ToArray());
document.Close();
fs.Dispose();
break;
}
page = copy.GetImportedPage(reader, currentPage);
copy.AddPage(page);
pagesRemaining--;
if (splitPoints.Contains(currentPage + 1) == true)
{
//Need to start a new document
//The call to copy.Close() MUST come before using fs.ToArray() because copy.Close() finalizes the document
fs.Flush();
copy.Close();
documents.Add(fs.ToArray());
document.Close();
fs.Dispose();
break;
}
}
copy = null;
page = null;
fs.Dispose();
}
if (reader != null)
{
reader.Close();
reader = null;
}
if (document != null)
{
document.Close();
document.Dispose();
document = null;
}
if (fs != null)
{
fs.Close();
fs.Dispose();
fs = null;
}
return documents;
}
据我所知,我能看到的唯一在线代码是VB,并不一定解决尺寸问题。
更新:
我们遇到OutofMemory异常,我认为这是大对象堆的问题。因此,一个想法是减少代码占用空间,这可能会减少堆上的大对象数量。
基本上,这是循环的一部分,遍历任意数量的PDF,然后将它们拆分并存储在数据库中。现在,我们不得不改变方法,一次完成所有这些(最后一次运行是各种大小的97 pdf),每5分钟通过系统运行5个pdf。这不是理想的,当我们将工具增加到更多客户端时,它不会很好地扩展。
(我们正在处理50 -100 meg pdf,但它们可能更大)。
答案 0 :(得分:2)
我也继承了这个确切的代码,似乎存在一个重大缺陷。在GetPDFSplitPoints
方法中,它会根据maxsize检查复制页面的总大小,以确定在哪个页面拆分文件。
在SplitPDF
方法中,当它到达发生拆分的页面时,此时的MemoryStream肯定低于允许的最大大小,并且还有一页将使其超出限制。但是在执行document.Close();
之后,MemoryStream
会添加更多内容(在我使用的PDF示例中,Length
的{{1}}从9 MB增加到19 MB在MemoryStream
之前和之后。我的理解是,复制页面的所有必要资源都会添加到document.Close
上
我猜我必须完全重写这段代码,以确保我不会超过最大尺寸,同时保留原始页面的完整性。