Această versiune localizată intră direct în Fix the HotPDF component reuse issue și folosește articolul englez actualizat ca reper tehnic pentru echipele Delphi, PDF și software documentar
Pagina transformă articolul de bază actualizat în puncte concrete de control pentru proiectare, implementare și validare
Ce a fost sincronizat din articolul englez
Textul de bază în engleză a fost extins cu context de implementare, decizii tehnice și exemple concrete, astfel că pagina trebuie citită ca un ghid de lucru, nu ca un rezumat scurt
Secțiuni importante din articolul de bază actualizat:
- Folosește mai întâi fișiere mici de intrare, ușor de reprodus
- Păstrează neschimbate numele produselor, API-urilor, fișierelor și valorile literale
- Salvează ieșirea validatorului și informațiile de versiune împreună cu fișierul eșantion generat
Alegeri practice de implementare
Pornește de la tipul de fișier, rezultatul așteptat și starea de eroare care trebuie afișată utilizatorului. Leagă apoi fiecare apel API de un rezultat verificabil, astfel încât validarea, logarea și suportul să poată reproduce cazul clientului
- Folosește mai întâi fișiere mici de intrare, ușor de reprodus
- Păstrează neschimbate numele produselor, API-urilor, fișierelor și valorile literale
- Salvează ieșirea validatorului și informațiile de versiune împreună cu fișierul eșantion generat
Verificare înainte de publicare
Verifică fișierul de ieșire cu aceleași instrumente pe care le va folosi clientul sau arhiva. Notează versiunea componentei, datele de test, versiunea validatorului și rezultatul observat pentru a urmări precis o regresie ulterioară
Lecturi conexe
Note suplimentare
Această completare transformă versiunea scurtă într-un ghid de lucru mai util și rămâne aliniată cu Fix the HotPDF component reuse issue și cu baza tehnică din articolul englez. Textul trebuie să arate clar cu ce tip de intrare pornește tema, ce rezultat este așteptat și în ce punct trebuie confirmat comportamentul prin validation
La rescriere contează ordinea deciziilor: mai întâi forma datelor, apoi limita schimbării, după aceea dependențele API și, la final, comportamentul rezultat. Dacă articolul menționează mai multe opțiuni, merită explicat și ce variantă este mai ușor de susținut în maintenance, support și în reproducerea unei probleme
Orice code block, nume de fișier, nume de API și valoare literal trebuie să rămână neschimbate. Explicația din jur poate fi mai amplă, dar exemplul de cod trebuie să fie o referință exactă, astfel încât cititorul să îl poată compara direct cu proiectul lui Delphi, C++Builder sau Lazarus/FPC
Secțiunea de validation ar trebui să menționeze un fișier de intrare mic, compararea rezultatului și notarea versiunii de component sau validator. Dacă pagina descrie un bug fix sau o migrare, traseul de reproducere, starea observată inițial și punctul de confirmare trebuie spuse clar, ca să poată fi urmărită orice regression fără presupuneri
O astfel de extindere face pagina utilă și după prima lectură: pentru reviewer ca explicație a deciziei, pentru support ca fundal de diagnostic și pentru echipa de întreținere ca notă de referință înainte de modificările viitoare
- Nu schimba numele produselor, API-urilor, fișierelor sau valorile literal
- Păstrează code block-urile exact așa cum sunt
- Descrie validation cu fișier de probă și rezultat comparabil
- Explică ordinea deciziilor, nu doar un rezumat foarte scurt
Exemple de cod suplimentare
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice.pdf';
Pdf.BeginDoc; // opens the document
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-042');
Pdf.EndDoc; // writes invoice.pdf, closes it out
finally
Pdf.Free; // one instance, one document
end;
end;
procedure WriteBatch(const Names: TArray<string>);
var
I: Integer;
Pdf: THotPDF;
begin
for I := 0 to High(Names) do
begin
Pdf := THotPDF.Create(nil); // new instance each pass
try
Pdf.FileName := Names[I] + '.pdf';
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 12);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Statement for ' + Names[I]);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
end;
var
Pdf: THotPDF;
PageCount: Integer;
begin
Pdf := THotPDF.Create(nil);
try
PageCount := Pdf.LoadFromFile('contract.pdf');
if PageCount > 0 then
begin
Pdf.CurrentPage.SetFont('Arial', [fsBold], 10);
Pdf.CurrentPage.TextOut(40, 30, 0, 'REVIEWED');
Pdf.SaveLoadedDocument('contract-reviewed.pdf');
end;
finally
Pdf.Free;
end;
end;
uses
System.SysUtils, System.IOUtils;
procedure WritePdfAtomically(const FinalPath: string);
var
Pdf: THotPDF;
TempPath: string;
begin
// Temp file in the SAME directory as the target: a rename inside one
// NTFS volume swaps the name atomically, while a cross-volume move
// degrades to copy-plus-delete and loses that guarantee
TempPath := TPath.Combine(TPath.GetDirectoryName(FinalPath),
TGUID.NewGuid.ToString + '.pdf.tmp');
try
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := TempPath;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-042');
Pdf.EndDoc; // the temp file is complete on disk here
finally
Pdf.Free;
end;
// Swap into place. TFile.Move refuses to overwrite, so clear a stale
// target first; if a viewer still holds the old file, the delete is
// what fails, loudly, before the good bytes are touched
if TFile.Exists(FinalPath) then
TFile.Delete(FinalPath);
TFile.Move(TempPath, FinalPath); // or: RenameFile(TempPath, FinalPath)
except
if TFile.Exists(TempPath) then
TFile.Delete(TempPath); // never strand a half-written temp file
raise;
end;
end;
// One output path per request: two concurrent jobs can never contend
// for the same name, so no rename dance and no lock to lose
OutName := Format('statement-%s-%s.pdf',
[CustomerId, TGUID.NewGuid.ToString.Trim(['{', '}'])]);
Pdf.FileName := TPath.Combine(OutputDir, OutName);