Hızlı Başlangıç

İlk belgenizi dakikalar içinde renderlayın

Bu kılavuz, boş bir Program.cs dosyasından tarayıcıda görüntülenen bir belgeye kadar bir ASP.NET Core uygulamasını götürür: sunucu kaydı, tam Viewer paketi (Viewer araç çubuğu, Viewer montajı ve isteğe bağlı Arama/Not ekleme şeritleri), varlık referansları, istemci başlatma, belge açma ve yürütme.

Host uygulaması, netstandard2.1'i destekleyen bir çalışma zamanını hedeflemelidir — .NET Core 3.0 veya daha yeni bir sürüm. Bu sürümle birlikte gelen referans uygulamaları net8.0 hedeflemektedir.

Sunucu kurulumu

AddDoconut() hizmetleri kaydeder; UseDoconutResources() ve UseDoconut() ara katmanı bağlar. Kaynak çağrısı önce gelmelidir. Oturum çağrıları da gereklidir — Doconut'un varsayılan belge güvenliği, her sayfa isteğini ASP.NET oturum durumu ile doğrular. Oturum durumu bir önbelleğe ihtiyaç duyar: AddDistributedMemoryCache() bir tane sağlar. Bir MVC veya Razor Pages uygulaması zaten bunu kaydeder, ancak minimal-API uygulaması kaydetmez ve önbellek olmadan uygulama Unable to resolve service for type 'IDistributedCache' hatasıyla başlatmada durur. Kurulum sırasında zaten Doconut kaydedildi mi? Bir sonraki bölüme atlayın.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // oturum durumu bir önbelleğe ihtiyaç duyar (MVC/Razor Pages zaten bir tane ekler)
builder.Services.AddSession(); // Doconut belge güvenliği ASP.NET oturum durumuna dayanır

app.UseSession();          // UseSession()'i UseDoconut()'dan önce çağırın
app.UseDoconutResources(); // UseDoconut()'dan önce kaydedilmelidir
app.UseDoconut();

Referans uygulama, tarihsel DocImage.axd istek biçimini korur ve belge ara katmanını eşleşen bir dalda monte eder. Bu, mevcut bir .NET Standard uygulamasını ilerletirken kopyalamanız gereken düzenlemedir, çünkü istemci her zaman olduğu gibi aynı URL'yi çağırmaya devam eder:

csharp
builder.Services.AddDoconut(options =>
{
    options.UnsafeMode      = false;   // Doconut'un oturum kontrolünün etkin kalmasını sağla
    options.ShowDoconutInfo = false;
});
builder.Services.AddDistributedMemoryCache(); // oturum durumu bir önbelleğe ihtiyaç duyar (MVC/Razor Pages zaten bir tane ekler)
builder.Services.AddSession(options =>
{
    options.IdleTimeout        = TimeSpan.FromSeconds(3600);
    options.Cookie.HttpOnly    = true;
    options.Cookie.IsEssential = true;
});

// Bazı belge formatlarında çok baytlı kodlamalar için gereklidir.
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseDoconutResources();   // BELGE dalından ÖNCE
app.MapWhen(
    context => context.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
    branch => branch.UseDoconut());

UseDoconut() bu sürümde seçenek almaz — her şey AddDoconut()'a taşınmıştır. MiddlewarePath bir koordinasyon değeridir; tek başına bir ASP.NET Core dalını eşlemez. ResourcesPath gömülü paketi /doconut-res adresinde sunar ve widget'ın resim kaynağı yolu da ResPath: 'doconut-res/images' olur.

Görüntüleyiciyi bir sayfaya ekleyin

Viewer, sayfanın gerekli çekirdeğidir. Render yüzeyi iki iç içe div kullanır:

html
<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Araç çubuğunu, modül montajlarını ve Viewer yüzeyini tek bir sayfa bileşeni olarak ele alın. Arama ve Not ekleme, gömülü şeritlerini isteğe bağlı montajlara enjekte eder, ancak bu modüller asla bağımsız değildir: her zaman aynı sayfadaki Viewer'a eklenirler.

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer gezinme, yakınlaştırma, Arama ve Not ekleme düğmeleri -->
</nav>

<div id="searchBarMount"></div>
<div id="annBarMount"></div>

<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Görüntüleyici varlıklarını referansla

Bir Razor görünümünde, enjekte edilen Viewer hizmeti, bağımlılık sırasına göre görüntüleyicinin <link> ve <script> etiketlerini yayar — widget bir jQuery eklentisidir, bu yüzden jQuery görüntüleyici betiklerinden önce yüklenmelidir:

html
@inject Doconut.Viewer Viewer

@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss = true,
    IncludeViewerCss    = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeBootstrap     = true,
    IncludeViewerScripts = true
}))

Tam Viewer paketini almak için Viewer ve modül kaynaklarını birlikte isteyin:

html
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss  = true,
    IncludeViewerCss     = true,
    IncludeSearchCss     = true,
    IncludeAnnotationCss = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery            = true,
    IncludeBootstrap         = true,
    IncludeViewerScripts     = true,
    IncludeSearchScripts     = true,
    IncludeSearchBar         = true,
    IncludeAnnotationScripts = true,
    IncludeAnnotationBar     = true
}))

IncludeViewerCss ve IncludeViewerScripts zorunlu çekirdek bayraklardır. Bunlar olmadan bir Search veya Annotation Ribbon örneği yayınlamayın; Viewer bağlamı ve bir docViewer örneği gerekir. ReferenceCss ve ReferenceScripts, mevcut lisans bu yeteneği vermediğinde isteğe bağlı bir modülün kaynaklarını atlar; çekirdek Viewer yine de başlar.

Bu çağrılar elle kopyalanmış betik dosyalarını değiştirir. Uygulama hâlâ kendi docViewer.js, documentLinks.js veya docViewer.UI.js dosyalarını yüklüyorsa, sayfa yayılan kaynaklardan çalıştığında bu etiketleri kaldırın — bkz. göç rehberi.

Görüntüleyiciyi başlat

İstemci tarafı widget'ı bir jQuery eklentisidir. Bu, gerçek başlatma seçeneklerinin (sözde kod değil) en temel kümesidir:

javascript
let searchBar = null;
let annBar = null;

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/',
    ResPath:    'doconut-res/images',
    onViewerReady: function () {
        // sayfalar görünür; burada bir yükleme çubuğunu gizlemek güvenlidir
    },
    // Gömülü şerit mevcut olduğunda ek açıklama yaşam döngüsü olaylarını iletin.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

Bu sayfanın çalışıp çalışmadığını belirleyen iki detay vardır:

  • Geri aramalar (callbacks) birer seçenektir. onViewerReady, onViewerBusy, onCopy ve onAutoLoadStatus seçenek nesnesine geçirilir. Önceki görüntüleyici, kapsayıcı kimliğinden türetilen global fonksiyon adlarını çağırıyordu; bu sürüm bunu yapmaz. Yalnızca global bir fonksiyon olarak bildirilen bir işleyici asla çalışmaz ve hiçbir şey raporlanmaz.
  • ResPath kaynak önekini gösterir, uygulama kökünü değil. Varsayılan ResourcesPath ile bu değer doconut-res/images olur. ResourcesPath'i değiştirdiyseniz, kendi önekinizle kullanın.

Bu iki durum da sessizce başarısız olur — bkz. Sorun Giderme ve göç rehberi.

Seçenek adlandırması gerçekten karışıktır — showThumbs, autoLoad ve pageZoom camelCase iken, FitType, BasePath ve ResPath PascalCase'dir. Tutarlı bir kural yoktur; adlandırmayı yanlış yaparsanız seçenek sessizce yok sayılır (widget varsayılanına geri döner, hata fırlatmaz).

Tam Viewer paketini birleştir

Her iki referans uygulaması da aşağıdaki parçaları tek bir sayfada birlikte kurar:

Paket parçasıGereklilikNasıl bağlanır
Viewer kaynakları, bağlama ve objViewerGerekliÇekirdek belge işleyici
Viewer araç çubuğuReferans kompozisyonunda gerekliHost işaretlemesi; düğmeler aynı objViewer'ı çağırır
Arama şeridiİsteğe bağlı, lisanslı modüldoconutSearchBar(...).attach(objViewer)
Açıklama şeridiİsteğe bağlı, lisanslı modüldoconutAnnotationBar(...).attach(objViewer)

Ana Viewer araç çubuğu host işaretlemesi olsa da Viewer ile birlikte kurulur ve izole bir kontrol olarak belgelenmemelidir. Bu, düzenini, etiketlerini, simgelerini ve yetkilendirme kurallarını uygulamanızın kontrolü altında tutarken, her düğmenin aynı Viewer örneğini çalıştırmasını sağlar:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <button type="button" onclick="objViewer.GotoPage(1)">First</button>
    <button type="button" onclick="objViewer.Next(false)">Previous</button>
    <button type="button" onclick="objViewer.Next(true)">Next</button>
    <button type="button" onclick="objViewer.GotoPage(objViewer.TotalPages())">Last</button>
    <button type="button" onclick="objViewer.Zoom(false)">Zoom out</button>
    <button type="button" onclick="objViewer.Zoom(true)">Zoom in</button>
    <button type="button" onclick="objViewer.FitType('width')">Fit width</button>
    <button type="button" onclick="objViewer.FitType('height')">Fit height</button>
    <button type="button" id="openSearch">Search</button>
    <button type="button" id="openAnnotations">Annotations</button>
</nav>

Her iki referans uygulamasının da kullandığı paket başlatma sırasını koruyun:

  1. Viewer ve lisanslı modüller için CSS'i yay.
  2. Viewer araç çubuğunu, Arama/Açıklama bağlamalarını ve Viewer bağlamasını birlikte render et.
  3. Viewer ve lisanslı modüller için betikleri yay.
  4. Host uygulamasının kendi araç çubuğu yardımcı betiğini yükle.
  5. docViewer'ı başlat ve ortaya çıkan objViewer'ı tut.
  6. Her lisanslı Arama veya Açıklama Şeridini başlat.
  7. Her Şeride attach(objViewer) çağır.
  8. Belgeyi aç ve Viewer ile modül istekleri için token'ı sakla.

Sunucu tarafı korumaları önemlidir: isteğe bağlı bir yetenek mevcut değilse, onun betiği yayımlanmaz, böylece jQuery eklenti işlevi bulunmaz.

html
<script>
    let currentToken = '';

    const refitViewer = () =>
        requestAnimationFrame(() => objViewer.Refit());

    @if (Viewer.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    searchBar.attach(objViewer);
        </text>
    }

    @if (Viewer.IsAnnotationEnabled)
    {
        <text>
    annBar = $('#annBarMount').doconutAnnotationBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    annBar.attach(objViewer);
        </text>
    }

    document.getElementById('openSearch').addEventListener('click', () => {
        if (!searchBar) return;
        searchBar.isOpen() ? searchBar.close() : searchBar.open();
    });

    document.getElementById('openAnnotations').addEventListener('click', () => {
        if (!annBar) return;
        annBar.isOpen() ? annBar.close() : annBar.open();
    });
</script>

Her iki gömülü bileşen de kendi Şerit DOM'unu üretir. Arama, Find, Options ve Results gruplarını içerir. Açıklama, yazar araçlarını, stil denetimlerini, kaydetme eylemlerini ve isteğe bağlı dışa aktarma/görüntü eylemlerini barındırır. Çubuklar open(), close(), reset() ve isOpen() metodlarını sunar; oluşturulduktan hemen sonra her zaman attach(objViewer) çağırın.

Yukarıdaki örnek, başlangıcı minimal tutmak için isteğe bağlı host geri aramalarını ve Açıklama dışa aktarma/görüntü uç noktalarını atlar. Tam özellik‑özel kurulum için Arama ve Açıklamalar bölümlerine, ya da host‑sahibi Viewer araç çubuğunu stillendirmek veya değiştirmek için Özel Temalar bölümüne bakın.

Bir belgeyi açma

Sunucu tarafı tek bir uç noktadır: enjekte edilen Viewer hizmeti belgeyi açar ve bir oturum belirteci döndürür. Açma işlemi bu sürümde eşzamansızdır.

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    // Belirteç opaktır — widget'a verin, asla kaydetmeyin veya kalıcı hale getirmeyin.
    string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

İstemci bu belirteci alır ve objViewer.View(token) ile widget'a verir:

javascript
fetch('/api/open', { method: 'POST' })
    .then(resp => resp.json())
    .then(data => {
        currentToken = data.token;
        objViewer.View(currentToken);
    });

İlk açmadan önce ön hazırlık yapmanız gerekmez. Uygulamanızı ileriye taşıyorsanız, tüm InitCache() çağrılarını ve onu koruyan bayrağı silin — yöntem artık mevcut değil.

Belgeyi kapatma

Kullanıcı görüntüleyiciden ayrıldığında veya yerine başka bir belge açtığında objViewer.Close() çağırın. Sunucu‑taraflı iş akışlarında viewer.CloseDocument(token) önbellekteki oturumu hemen kaldırır, render motorunu serbest bırakır, güvenlik işaretçisini siler ve belirteci iptal eder. Kaydırmalı süresi dolma da aynı temizlik işlemini yapar, ancak büyük belgeler için açıkça kapatma önerilir.

Tamamlanan istek akışı şudur:

text
AddDoconut + ara katman
    -> CSS/skriptleri işleyip div'i monte et
    -> docViewer'ı başlat
    -> OpenDocumentAsync
    -> opak belirteci döndür
    -> objViewer.View(token)
    -> sayfa/arama/notasyon istekleri
    -> Close / CloseDocument

Belirteci bir taşıyıcı kimlik bilgisi gibi ele alın: asla kaydetmeyin, asla kalıcı hale getirmeyin, sadece widget'a verin. Belirteç, sunucudaki canlı bir belge oturumunu tanımlar ve oturum sona erdiğinde çalışmayı durdurur — yeni bir belirteç almak için belgeyi yeniden açın.

Çalıştırma

wwwroot/files/Sample.pdf konumuna bir PDF koyun, dotnet run komutunu çalıştırın ve widget'ı barındıran sayfayı açın. İlk sayfa görüntüleyicide, sol tarafta bir küçük resim paneliyle birlikte işlenir. Eğer işlenmezse, Sorun Giderme bölümüne bakın.

Lisans olmadan ne elde edersiniz

Eksik bir lisans hata vermez. Görüntüleyici normal şekilde işlenir, ancak her sayfa bir değerlendirme filigranı taşır. Doconut'un bir lisans bulma ve bulduktan sonra nelerin değiştiği hakkında bilgi için Lisans Kurulumu bölümüne bakın.

Bu sayfa yardımcı oldu mu?