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时释放上一份的内存