Hızlı Başlangıç

İlk belgenizi dakikalar içinde render edin

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

Ana uygulama, 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 gönderilen referans uygulamaları net8.0'i hedefler.

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 durumuna karşı doğrular. Oturum durumu bir önbellek gerektirir: AddDistributedMemoryCache() bir tane sağlar. Bir MVC veya Razor Pages uygulaması zaten bunu kaydeder, ancak minimal-API uygulaması kaydetmez ve onsuz uygulama, Unable to resolve service for type 'IDistributedCache' ile başlangıçta durur. Kurulum sırasında Doconut zaten 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()'ı 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 bağlar. Bu, mevcut bir .NET Standard uygulamasını ileriye taşırken kopyalamanız gereken düzenlemedir, çünkü istemci her zaman yaptığı aynı URL'yi çağırmaya devam eder:

csharp
builder.Services.AddDoconut(options =>
{
    options.UnsafeMode      = false;   // Doconut'un oturum kontrolünün etkin tutulması
    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();   // ÖNCE belge dalı
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şındı.

MiddlewarePath bir koordinasyon değeridir; tek başına bir ASP.NET Core dalını eşlemez. ResourcesPath gömülü paketi /doconut-res'de sunar ve widget'ın görüntü kaynağı yolu bu nedenle ResPath: 'doconut-res/images''dir.

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 bağlamalarını ve Viewer yüzeyini tek bir sayfa kompozisyonu olarak ele alın. Arama ve Not ekleme, gömülü şeritlerini isteğe bağlı bağlamalara 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">
    <!-- Görüntüleyici gezinme, yakınlaştırma, Arama ve Açıklama 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ına referans ver

Bir Razor görünümünde, enjekte edilen Viewer hizmeti, görüntüleyicinin <link> ve <script> etiketlerini bağımlılık sırasına göre üretir — 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. Asla bir
Search veya Annotation Ribbon örneğini, bunlar, Viewer montajı ve bir docViewer
örnek. 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ış script dosyalarını değiştirir. Uygulama hâlâ kendi
docViewer.js, documentLinks.js veya docViewer.UI.js dosyalarını yüklüyorsa, sayfa
emitted kaynaklardan çalışmaya başladıktan sonra bu etiketleri kaldırın — bkz. geçiş 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) minimal bir 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 göstergesini gizlemek güvenli
    },
    // Ek açıklama yaşam döngüsü olaylarını, mevcut olduğunda gömülü şeride yönlendir.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

İki detay, bu sayfanın çalışıp çalışmayacağını belirler:

  • Geri aramalar bir seçenektir. onViewerReady, onViewerBusy, onCopy, ve
    onAutoLoadStatus seçenek nesnesine geçirilir. Önceki viewer, container id'sinden global
    fonksiyon adlarını türetip çağırıyordu; bu sürüm bunu yapmaz. Sadece global bir
    fonksiyon olarak bildirilen bir işleyici hiçbir zaman çalışmaz ve hiçbir şey raporlanmaz.
  • ResPath, kaynak önekini gösterir, uygulama kökü değil. Varsayılan
    ResourcesPath ile, bu değer doconut-res/images. ResourcesPath'ı değiştirdiyseniz, kendi
    önekinizi kullanın.

Her iki durum da sessizce başarısız olur — bkz. Sorun Giderme ve geçiş rehberi.

Seçenek büyük/küçük harf kullanımı gerçekten karışık — showThumbs, autoLoad ve pageZoom camelCase iken, FitType, BasePath ve ResPath PascalCase'dir. Tutarlı bir kural yoktur; büyük/küçük harfi yanlış verirseniz seçenek sessizce yok sayılır (widget varsayılanına geri döner, hata atmaz).

Tam Viewer paketini birleştir

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

Paket parçasıGereksinimNasıl bağlanır
Viewer kaynakları, montaj ve objViewerGerekliÇekirdek belge işleyici
Viewer araç çubuğuReferans bileşiminde gerekliHost işaretlemesi; düğmeler aynı objViewer'ı çağırır
Search şeridiİsteğe bağlı, lisanslı modüldoconutSearchBar(...).attach(objViewer)
Annotation ş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
asla izole bir kontrol olarak belgelenmemelidir. Bu, düzenini, etiketlerini, simgelerini ve
yetkilendirme kurallarını uygulamanızın kontrolü altında tutar, her düğme aynı
Viewer örneğini çalıştırır:

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 uygulama tarafından kullanılan paket başlatma sırasını koruyun:

  1. Viewer ve lisanslı modüller için CSS üretin.
  2. Viewer araç çubuğunu, Search/Annotation montajlarını ve Viewer montajını birlikte render edin.
  3. Viewer ve lisanslı modüller için script'leri üretin.
  4. Host uygulamanın kendi araç çubuğu yardımcı script'ini yükleyin.
  5. docViewer'ı başlatın ve ortaya çıkan objViewer'ı tutun.
  6. Her lisanslı Search veya Annotation şeridini başlatın.
  7. Her şeritte attach(objViewer)'ı çağırın.
  8. Belgeyi açın ve Viewer ve modül istekleri için token'ını saklayın.

Sunucu tarafı korumaları önemlidir: isteğe bağlı bir yetenek mevcut olmadığında,
script üretilmez, bu yüzden jQuery eklenti fonksiyonu 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 Ribbon DOM'unu üretir. Search, Find, Options ve Results gruplarını içerir. Annotation, yazar araçlarını, stil kontrollerini, kaydetme eylemlerini ve isteğe bağlı dışa aktarım/görüntü eylemlerini içerir. Çubuklar open(), close(), reset() ve
isOpen()'ı ortaya çıkar; oluşturduktan sonra her zaman bir kez attach(objViewer)'ı çağırın.

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

Bir belge açın

Sunucu tarafı tek bir uç noktadır: enjekte edilen Viewer servisi 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) =>
{
    // Token opak — widget'e ver, asla günlüğe kaydetme veya saklama.
    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 ısıtılacak bir şey yoktur. Uygulamayı ileriye taşıyorsanız, herhangi bir InitCache() çağrısını ve onu koruyan bayrağı silin — yöntem artık mevcut değil.

Belgeyi kapat

Kullanıcı görüntüleyiciden ayrıldığında veya yerine bir belge açtığında objViewer.Close() çağırın. Sunucu yönlendirmeli iş akışlarında, viewer.CloseDocument(token) önbelleğe alınmış 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 sonunda aynı temizlik işlemini yapar, ancak büyük belgeler için açıkça kapatma önerilir.

Tamamlanmış istek akışı şudur:

text
AddDoconut + middleware
    -> render CSS/scripts and mount div
    -> initialize docViewer
    -> OpenDocumentAsync
    -> return opaque token
    -> objViewer.View(token)
    -> page/search/annotation requests
    -> Close / CloseDocument

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

Çalıştır

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

Lisans olmadan neler elde edersiniz

Eksik bir lisans hata vermez. Görüntüleyici normal şekilde renderlanır, ancak her sayfa bir değerlendirme filigranı taşır. Doconut'un bir lisans nasıl bulduğunu ve bulduktan sonra nelerin değiştiğini görmek için Lisans Kurulumu bölümüne bakın.

Bu sayfa yardımcı oldu mu?