const PdfDefaultStorageMemoryLimit = 64 * 1024 * 1024;
type TPdfStorageBackend = (psbMemory, psbTemporaryFile);
constructor TPdfRandomAccessStore.Create(AMemoryLimit: Int64 = PdfDefaultStorageMemoryLimit; const ATemporaryDirectory: string = '');
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Int64; Origin: TSeekOrigin): Int64; override;
function Write(const Buffer; Count: Longint): Longint; override;
function ReadAt(Offset: Int64; var Buffer; Count: Longint): Longint;
function WriteAt(Offset: Int64; const Buffer; Count: Longint): Longint;
procedure CopyToStream(Destination: TStream; BufferSize: Integer = 1048576);
procedure Flush;
procedure SpillToDisk;
property Backend: TPdfStorageBackend;
property MemoryBytes: Int64;
property MemoryLimit: Int64;
property PeakMemoryBytes: Int64;
property Spilled: Boolean;
property TemporaryDirectory: string;
property TemporaryFileName: string;
property SaveMemoryLimit: Int64;
property SaveTemporaryDirectory: string;
property LastSaveSpillCount: Integer;
property LastSaveLargestMemoryBuffer: Int64;
| SaveMemoryLimit | Максимальная ёмкость опорной памяти каждого внутреннего хранилища сохранения до переноса на диск; по умолчанию 64 MiB |
| SaveTemporaryDirectory | Существующий каталог для файлов переноса; пустое значение использует временный каталог процесса |
| LastSaveSpillCount | Количество внутренних рабочих хранилищ, выполнивших перенос, в ходе самого последнего конвейера сохранения |
| LastSaveLargestMemoryBuffer | Наибольшая единичная ёмкость опорной памяти, наблюдавшаяся в ходе самого последнего конвейера сохранения |
TPdfRandomAccessStore наследует от TStream и помимо позиционированного ввода-вывода, независимого от курсора, поддерживает обычные последовательные чтение, запись, позиционирование и изменение размера
Данные остаются в динамически изменяемом буфере памяти, пока его логический конец не превышает MemoryLimit
Первая операция, пересекающая потолок, создаёт монопольно владеемый временный файл, однократно копирует существующие байты, очищает буфер памяти и сохраняет файловый бэкенд до конца жизни хранилища
Временный дескриптор использует флаги удаления-при-закрытии и произвольного доступа, не допускает совместного использования и удаляется при нормальном разрушении или откате конструктора
Отдельные операции сериализуются внутренней критической секцией; ReadAt и WriteAt предпочтительны, когда конкурирующие вызывающие стороны не должны спорить за последовательный курсор
Хранилище можно передать напрямую в LoadCustomDocument; блочные обратные вызовы PDFium используют позиционированные чтения и не меняют курсор хранилища
TPdf использует настроенную политику для базовых сохранений, каждого рабочего пространства постобработки сохранённого PDF и промежуточных стадий конвертации по стандартам, валидации, шифрования, DSS и PAdES
Встроенное инкрементальное восстановление xref-потоков читает окна хвоста и словарей фиксированного размера, а затем применяет проверенные правки, копируя неизменённые диапазоны ограниченными порциями
MemoryBytes сообщает ёмкость опорного буфера, а не логический размер содержимогоPeakMemoryBytes никогда не превышает MemoryLimitLastSaveLargestMemoryBuffer - это наибольшее единичное внутреннее хранилище, а не сумма одновременно активных хранилищTBytes, которые всё ещё создаёт конкретный парсер, компрессор, валидатор или подписывающий модульMemoryLimit должен быть между нулём и High(Integer)FPDF_FILEACCESS сохраняет ограничение длины файла 4 GiB, даже когда само хранилище имеет больший размер Int64TemporaryFileName служит только для диагностики; живой файл открыт монопольно и не должен открываться повторно вызывающим кодом
var
Store: TPdfRandomAccessStore;
begin
Pdf.SaveMemoryLimit := 16 * 1024 * 1024;
Pdf.SaveTemporaryDirectory := TPath.GetTempPath;
Pdf.SaveAs('output.pdf');
Log(Pdf.LastSaveSpillCount, Pdf.LastSaveLargestMemoryBuffer);
Store := TPdfRandomAccessStore.Create(4 * 1024 * 1024);
try
Store.CopyFrom(SourceStream, SourceStream.Size);
Store.Position := 0;
Pdf.LoadCustomDocument(Store, False);
finally
Pdf.Active := False;
Store.Free;
end;
end;