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 | Maximální kapacita záložní paměti každého interního ukládacího store před přelitím; výchozí je 64 MiB |
| SaveTemporaryDirectory | Existující adresář používaný pro přelité soubory; prázdná hodnota použije dočasný adresář procesu |
| LastSaveSpillCount | Počet interních pracovních store, které se přelily během posledního uložovacího kanálu |
| LastSaveLargestMemoryBuffer | Největší pozorovaná kapacita jediné záložní paměti během posledního uložovacího kanálu |
TPdfRandomAccessStore dědí z TStream a kromě pozicovaného I/O nezávislého na kurzoru podporuje běžné sekvenční čtení, zápis, přesuny kurzoru a změny velikosti
Data zůstávají v dynamicky dimenzovaném paměťovém bufferu, dokud je jeho logický konec na MemoryLimit nebo pod ním
První operace, která strop překročí, vytvoří exkluzivní dočasný soubor, jednou zkopíruje stávající bajty, vyčistí paměťový buffer a pro zbytek života store ponechá souborový backend
Dočasný handle používá příznaky delete-on-close a random-access, nepovoluje žádné sdílení a při běžném zániku nebo rollbacku konstruktoru se odstraní
Jednotlivé operace serializuje interní kritická sekce; když si souběžní volající nesmí konkurovat o sekvenční kurzor, dává se přednost ReadAt a WriteAt
Store lze předat přímo do LoadCustomDocument; bloková zpětná volání PDFium používají pozicované čtení a kurzor store nemění
TPdf používá nakonfigurovanou politiku pro základní ukládání, každý post-processingový workspace uloženého PDF a mezistupeň konverzí standardů, validace, šifrování, DSS a PAdES
Nativní oprava inkrementálních xref streamů čte okna ocasu a slovníků pevné velikosti a poté aplikuje validované úpravy, přičemž nezměněné rozsahy kopíruje v ohraničených blocích
MemoryBytes hlásí kapacitu záložního bufferu, nikoli velikost logického obsahuPeakMemoryBytes nikdy nepřekročí MemoryLimitLastSaveLargestMemoryBuffer je největší jediný interní store, nikoli součet současně aktivních storeTBytes, která stále vytváří konkrétní parser, kompresor, validátor nebo podepisovatelMemoryLimit musí ležet mezi nulou a High(Integer)FPDF_FILEACCESS si zachovává limit délky souboru 4 GiB, i když má záložní store sám větší velikost Int64TemporaryFileName slouží jen pro diagnostiku; živý soubor je otevřen exkluzivně a volající ho nesmí otevírat znovu
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;