PDFium Component, bir düzenleme günlüğü aracılığıyla bir PDF düzenleyiciye gerçek belge düzeyinde geri alma ve yineleme, artı bir çökme kurtarma paketi verir. Değişiklikleri BeginEditTransaction ve CommitEditTransaction içine sararsınız ve her kaydedilen işlem, UndoEdit ve RedoEdit'in her iki yönde de yeniden oynatabileceği çift yönlü bir delta haline gelir. SaveRecoverySnapshot bu günlüğü kalıcı hale getirir, böylece oturum ortasında sonlandırılan bir uygulama kullanıcının çalışmasını yeniden inşa edebilir
Bunun doldurduğu boşluk özeldir. Yerel geri alma yeteneği yalnızca o anda odaklanmış olan form alanına uygulanır, bu yüzden bir metin kutusu yalnızca kendi düzenlemelerini hatırlar, başka hiçbir şeyi hatırlamaz. Sayfa ekleme, silme ve yeniden sıralama, sayfa nesnesi değişiklikleri, açıklamalar, ekler ve meta veri hiç günlüğe sahip değildir. Yalnızca bunun üzerine kurulu bir düzenleyici, bir alanın içinde ve başka hiçbir yerde geri alma sunabilir; bu, kullanıcıların geri alma ile kastettiği şey değildir
Neden Bir İşlem Günlüğü Yerine Anlık Görüntüler?
Bariz tasarım, anlamsal işlemleri — "sayfa 4 silindi", "açıklama 7 taşındı" — kaydetmek ve tersine çevirmektir. Bu, işlem kümesi büyüyene kadar işe yarar; o noktada her yeni özelliğin bir tersine ihtiyacı vardır ve tersi tam olmayan herhangi bir işlem, uzun bir geri alma zincirinde belgeyi sessizce bozar
Bunun yerine günlük, belge durumunu işlem sınırlarında yakalar ve farkı saklar. Her delta, en uzun ortak öneki ve soneki tutar ve hem kaldırılan hem eklenen baytları taşır, bu yüzden ileri veya geri uygulanabilir. Yeni düzenleme özellikleri hiçbir geri alma desteğine ihtiyaç duymaz: değiştirdikleri her ne ise anlık görüntünün içindedir
Bu yaklaşım bir ön koşula bağlıdır. Sıradan tam bir kayıt, belirlenimci olmayan tanımlayıcılar ve zaman alanları üretir, bu yüzden değiştirilmemiş bir belgeyi iki kez kaydetmek farklı baytlar verebilir. Bu yüzden anlık görüntüler önce yeniden üretilebilir çıktı yolu üzerinden normalize edilir. Bu adım olmadan boş bir işlem bir değişiklik gibi görünürdü ve geri alma kendi doğrulamasında başarısız olurdu, çünkü kaydetme sırasında hesapladığı özet daha sonra belgeyle eşleşmezdi
Pratikte İşlemler
Her işlem isteğe bağlı bir etiket alır; bir düzenleyicinin geri alma menüsünde gösterdiği şey budur:
uses
PDFium;
var
Pdf: TPdf;
Options: TPdfEditJournalOptions;
Info: TPdfEditJournalInfo;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'contract.pdf';
Pdf.LoadDocument;
Options := TPdfEditJournalOptions.Default;
Options.MaxEntries := 50; // geri alma derinliği
Options.MaxStoredBytes := 256 * 1024 * 1024;
Pdf.ConfigureEditJournal(Options);
Pdf.BeginEditTransaction('Delete cover page');
try
Pdf.DeletePage(1);
if not Pdf.CommitEditTransaction then
raise Exception.Create('commit failed - document was reloaded');
except
Pdf.RollbackEditTransaction;
raise;
end;
Info := Pdf.GetEditJournalInfo;
Writeln(Format('entries=%d position=%d stored=%d bytes',
[Info.EntryCount, Info.Position, Info.StoredBytes]));
if Pdf.EditCanUndo then
Pdf.UndoEdit; // sayfa geri gelir
finally
Pdf.Free;
end;
end;
Başarısız olan bir kaydetme — yakalama başarısız olduğu, bir bütçe aşıldığı veya delta oluşturulamadığı için — etkin bir işlem veya yarı yazılmış bir günlük bırakmak yerine BeginEditTransaction'da yakalanan temel çizgiyi geri yükler ve yeniden yükler. Bu, en çok önemli olan başarısızlık modudur, çünkü tutarsız bir durumdaki bir günlük, sonraki her geri almayı zehirler
Her Adımda Doğrulama
Her delta, önek uzunluğu ve her iki yük ile birlikte belgenin öncesi ve sonrasının SHA-256 özetini saklar. Geri alma, yineleme, içe aktarılan yeniden oynatma ve ters yeniden inşa, herhangi bir şeye dokunmadan önce geçerli özeti ve değiştirmeyi amaçladıkları bölgeyi kontrol eder, ardından sonraki özeti doğrular
Günlük boyunca hareket eşit derecede dikkatlidir. Konum, yalnızca hedef PDF bağımsız bir belge nesnesi tarafından doğrulandıktan ve geçerliyi başarıyla değiştirdikten sonra ilerler. Bu başarısız olursa, geçerli anlık görüntü bir yedek olarak geri yüklenir, bu yüzden başarısız bir geri alma kullanıcıyı bozuk bir durumda değil oldukları yerde bırakır
Serileştirilmiş biçim, girdi olarak güvenilmez, veri olarak kontrol edilir: sihirli sayı, sürüm, girdi ve konum değerleri, özet zinciri, etiket uzunlukları, yama uzunlukları ve toplam depolama bütçesinin hepsi doğrulanır. İçe aktarılan bir günlük, kırpılmış, düzenlenmiş veya farklı bir sürüm tarafından üretilmiş olabilecek bir dosyadır ve onu düşmanca olarak ele almak tek güvenli duruştur
Günlük Dolduğunda Ne Olur
Üç sınır büyümeyi sınırlar: girdi sayısı, kümülatif delta baytları ve tek bir anlık görüntünün boyutu. Kapasiteye ulaşıldığında en eski girdi çıkarılır ve kök parmak izi ilerler
Bu son kısmın, etrafında tasarım yapmaya değer bir sonucu vardır. Dışa aktarılan bir günlük, yalnızca bildirdiği kök parmak iziyle veya kaydettiği bir parmak iziyle eşleşen bir belgeye uygulanabilir. Çıkarma gerçekleştikten sonra günlük artık özgün dosyaya geri ulaşamaz. Bu yüzden otomatik kaydetme, eşleşen kök anlık görüntüsünü ve günlüğü tek bir atomik kurtarma birimi olarak ele almalıdır — temeli olmadan günlüğü tutmak, yeniden oynatılamayacak bir şeyi tutmaktır
Çökme Kurtarma Paketleri
Kurtarma paketi, kaynak PDF'yi kasıtlı olarak gömmez. Kaynağın görünen adını, kaynak ve kurtarılan durumların SHA-256 parmak izlerini ve düzenleme günlüğünü saklar. Bu yüzden kurtarma, çağıranın önce yüklediği özgün dosyayı gerektirir; paket ardından günlüğü geriye ve ileriye yeniden oynatarak her iki parmak izini de doğrular:
// Her başarılı kaydetmeden sonra kurtarma dosyasını yenile
Pdf.BeginEditTransaction('Redact account numbers');
if Pdf.CommitEditTransaction then
Pdf.SaveRecoverySnapshot('contract.recovery');
// Bir sonraki oturumda, bir çökmeden sonra: özgünü yükle, sonra geri yükle
Pdf.FileName := 'contract.pdf';
Pdf.LoadDocument;
Pdf.RestoreRecoverySnapshot('contract.recovery');
Kaynağı gömmemek, kurtarma dosyalarını küçük tutar; herhangi bir boyuttaki bir belgede kaydetme başına otomatik kaydetmeyi uygun maliyetli yapan şey budur. Bir dış özet, başlığı, kaynak adını ve günlüğü kapsar, bu yüzden kırpılmış veya kurcalanmış bir paket herhangi bir delta ayrıştırılmadan önce reddedilir ve toplam okuma hacmi üst sınırlandırılır
Dosya yazmaları hedef dizindeki geçici bir dosyaya gider ve ardından atomik olarak değiştirilir; kurtarma yolunu kaynak PDF olarak ayarlamak açıkça reddedilir. Otomatik kaydetme yalnızca başarılı, değişmiş bir kaydetme, geri alma veya yinelemeden sonra çalışır. Disk yazması başarısız olursa bellek içi belge ve günlük durumları zaten geçerlidir, bu yüzden istisna bir veri kaybı değil bir kalıcılık başarısızlığı bildirir ve çağıran yolu düzeltip yeniden deneyebilir
İmzalı Belgeler Varsayılan Olarak Reddedilir
Bir işlem anlık görüntüsü, özgün imzalı baytlar değil yeni bir normalize edilmiş revizyondur, bu yüzden imzalı bir belgede bir işlemi kaydetmek imzayı geçersiz kılar. Böyle bir belgede bir işlem başlatmak, çağıran AllowSignedDocument'ı geçirmedikçe reddedilir ve günlük içe aktarma ile kurtarma geri yükleme de varsayılan olarak aynı reddi izler
Bu, bir yasak değil kasıtlı bir hız engelidir. Bazı iş akışları meşru bir şekilde imzalı bir belgeyi düzenler ve daha sonra yeniden imzalar ve bayrak onlar için vardır. Önlediği şey kazara olan durumdur; burada bir düzenleyici, kullanıcının hâlâ imzalı olduğuna inandığı bir belgeden sessizce geçerliliği söker. Bu hikayenin doğrulama tarafı, PDF dijital imzalarını ve PAdES düzeylerini inceleme başlığında ele alınmıştır
Bir düzenleyici için üç alışkanlık günlüğü karşılığını verir hale getirir. Her kullanıcı tarafından görülebilir eylemi tek bir etiketli işleme sarın, böylece geri alma menüsü sizin çağrı yığınınız gibi değil kullanıcının zihinsel modeli gibi okunur. Girdi sınırını belgeye göre boyutlandırın, çünkü 200 MB'lık bir taramanın elli anlık görüntüsü mütevazı bir ayar değildir. Ve kurtarma anlık görüntüsünü bir zamanlayıcı yerine her kaydetmede yazın, çünkü bir zamanlayıcı, kaybedilen çalışmanın tam olarak son tik'ten sonra ne olduğu olacağını garanti eder. Bundan yararlanan belge düzeyindeki düzenleme işlemleri, şifrelenmiş PDF artımlı güncellemeleri başlığında ele alınmıştır
Düzenleme günlüğü tutma, kurtarma paketleri ve altlarındaki düzenleme ilkelleri, Delphi, C++Builder ve Lazarus için aynı bileşende gelir; tam API, Delphi için PDFium Component sayfasında açıklanmıştır