PdfiumViewer组件扩展(Pdfium.Net.Free)--打开大文件处理

项目地址:

Pdfium.Net:https://github.com/1000374/Pdfium.Net.Free

PdfiumViewer:https://github.com/1000374/PdfiumViewer

Pdfium.Net.Free 支持

  • .NETFramework 4.0

  • .NETFramework 4.5

  • .NETStandard 2.0

  • .Net8.0

可以和PdfiumViewer.Free共同使用预览、编辑pdf,也可以直接引用Pdfium.Net.Free 操作pdf,Pdfium.Net.Free封装了现有Pdfium的函数,实现了部分操作pdf的功能,部分功能等待后续~~

PDFium支持打开文件支持传入文件流

加载PDF到内存流(此种方式不占用文件):

var stream=new MemoryStream(File.ReadAllBytes(fileName));

var doc=PdfDocumentGdi.Load(this, stream);

但是当pdf文件超过85000字节后,内存既不像引用类型那样分配到普通堆上,也不像值类型那样分配到栈上,而是分配到了一个特殊的称为LOH的内部堆上,这部分的内存只有在GC执行完全回收,也就是回收二代内存的时候才会回收。

因此,考虑如下情形:

假设你的程序每次都要分配一个大型对象(大于85000字节),但却很少分配小对象,导致2代垃圾回收从不执行,即使这些大对象不再被引用,依然得不到释放,最终导致内存泄漏。

解决方案:

1.不考虑文件被占用可使用:

var filestm = new FileStream(fileName, FileMode.Open);
var doc=PdfDocumentGdi.Load(this, stream);

2.但是 有些情况下不想占用文件:

nuget 引用 Microsoft.IO.RecyclableMemoryStream

RecyclableMemoryStreamManager manager;
 int multiple = 5;
 int blockSize = multiple * 1024;
 int largeBufferMultiple = 1024 * 1024;
 int maxBufferSize = 16 * largeBufferMultiple;
 int maximumFreeSmallPoolBytes = 100 * blockSize / multiple;
 int maximumFreeLargePoolBytes = maxBufferSize * 4;

 var options = new RecyclableMemoryStreamManager.Options()
 {
     BlockSize = blockSize,
     LargeBufferMultiple = largeBufferMultiple,
     MaximumBufferSize = maxBufferSize,
     GenerateCallStacks = true,
     AggressiveBufferReturn = true,
     MaximumLargePoolFreeBytes = maximumFreeLargePoolBytes,
     MaximumSmallPoolFreeBytes = maximumFreeSmallPoolBytes,
 };
 manager = new RecyclableMemoryStreamManager(options);
 
var stream = manager.GetStream();
 using (var filestm = new FileStream(fileName, FileMode.Open))
 {
     filestm.CopyTo(stream);
 }
var doc=PdfDocumentGdi.Load(this, stream);

这两种方式都可以在打开第二份pdf时释放上一份的内存

 

 

  

posted @ 2024-01-25 18:27  小树禾小央  阅读(60)  评论(0编辑  收藏  举报