Mulai Cepat

Render dokumen pertama Anda dalam hitungan menit

Panduan ini membawa aplikasi ASP.NET Core dari Program.cs yang kosong hingga dokumen yang dirender di peramban: pendaftaran server, paket Penampil lengkap (bilah alat Penampil, penempatan Penampil, dan pita Pencarian/Anotasi opsional), referensi aset, inisialisasi klien, pembukaan dokumen, dan eksekusi.

Pengaturan Server

AddDoconut() mendaftarkan layanan; UseDoconutResources() dan UseDoconut() menghubungkan middleware. Panggilan sumber daya harus datang pertama. Panggilan sesi juga diperlukan — keamanan dokumen Doconut default memvalidasi setiap permintaan halaman terhadap status sesi ASP.NET. Sudah mendaftarkan Doconut selama Instalasi? Lewati ke bagian berikutnya.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession(); // Doconut document security rides on ASP.NET session state

app.UseSession();          // call UseSession() before UseDoconut()
app.UseDoconutResources(); // must be registered before UseDoconut()
app.UseDoconut();

Untuk tata letak jalur gaya produksi, petakan middleware dokumen ke cabang eksplisit dan pertahankan empat pengaturan jalur tetap selaras:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "Doconut.Viewer.lic");
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});
builder.Services.AddSession();

app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());

MiddlewarePath adalah nilai koordinasi; ia tidak memetakan cabang ASP.NET Core secara otomatis. Dalam contoh ini host memetakan /doconut, sehingga klien harus menggunakan BasePath: '/doconut'. ResourcesPath menyajikan bundel tersemat di /doconut-res, dan jalur sumber daya gambar widget adalah ResPath: '/doconut-res/images'.

Tambahkan penampil ke halaman

Penampil adalah inti yang diperlukan pada halaman. Permukaan render‑nya menggunakan dua div bersarang:

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

Anggap bilah alat, penempatan modul, dan permukaan Penampil sebagai satu komposisi halaman. Pencarian dan Anotasi menyuntikkan pita tersemat mereka ke penempatan opsional, tetapi modul‑modul tersebut tidak pernah berdiri sendiri: mereka selalu menempel pada Penampil di halaman yang sama. Gunakan urutan yang sama seperti Doconut.TestApp dan Doconut.TestApp.Distributed:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer navigation, zoom, Search, and Annotation buttons -->
</nav>

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

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

Referensikan aset penampil

Di tampilan Razor, layanan Viewer yang disuntikkan menghasilkan tag <link> dan <script> penampil dalam urutan ketergantungan — widget adalah plugin jQuery, sehingga jQuery harus dimuat sebelum skrip penampil:

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
}))

Untuk paket Penampil lengkap, minta sumber daya Penampil dan modul secara bersamaan:

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 dan IncludeViewerScripts adalah flag inti yang wajib. Jangan pernah memublikasikan contoh Pita Pencarian atau Anotasi tanpa mereka, penempatan Penampil, dan sebuah instance docViewer. ReferenceCss dan ReferenceScripts menghilangkan sumber daya modul opsional ketika lisensi saat ini tidak memberikan kemampuan tersebut; Penampil inti tetap dapat dijalankan.

Inisialisasi penampil

Widget sisi klien adalah plugin jQuery. Berikut adalah sekumpulan opsi inisialisasi nyata (bukan pseudocode):

javascript
let searchBar = null;
let annBar = null;

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/doconut',
    ResPath:    '/doconut-res/images',
    onViewerReady: function () {
        // pages are visible; safe to hide a loading spinner here
    },
    // Forward annotation lifecycle events to the embedded ribbon when it is present.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

Penulisan kapitalisasi opsi memang campur‑aduk — showThumbs, autoLoad, dan pageZoom memakai camelCase, sementara FitType, BasePath, dan ResPath memakai PascalCase. Tidak ada aturan konsisten; jika penulisan kapitalisasi salah, opsi akan diabaikan secara diam‑diam (widget akan kembali ke nilai baku alih‑alih melempar kesalahan).

Susun paket Penampil lengkap

Kedua aplikasi referensi .NET 6 memasang bagian‑bagian berikut secara bersamaan pada satu halaman:

Bagian paketKebutuhanCara terhubung
Sumber daya Penampil, penempatan, dan objViewerDiperlukanRenderer dokumen inti
Bilah alat PenampilDiperlukan dalam komposisi referensiMarkup host; tombol memanggil objViewer yang sama
Pita PencarianOpsional, modul berlisensidoconutSearchBar(...).attach(objViewer)
Pita AnotasiOpsional, modul berlisensidoconutAnnotationBar(...).attach(objViewer)

Meskipun bilah alat Penampil utama adalah markup host, ia dipasang bersama Penampil dan tidak pernah didokumentasikan sebagai kontrol terpisah. Ini menjaga tata letak, label, ikon, dan aturan otorisasi di bawah kendali aplikasi Anda sementara setiap tombol mengendalikan instance Penampil yang sama:

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>

Bilah alat referensi lengkap juga menyalin wwwroot/js/viewerToolbar.js ke dalam aplikasi host untuk fungsi rotasi, thumbnail, cetak, layar penuh, tata letak, dan pembantu status tombol. Muat berkas host itu setelah Viewer.ReferenceScripts(...). Simpan pembantu dan markup <nav id="toolbar">‑nya bersama saat menyalin implementasi demo penuh.

Pertahankan urutan inisialisasi paket yang dipakai oleh kedua aplikasi referensi:

  1. Emit CSS untuk Penampil dan modul berlisensi.
  2. Render bilah alat Penampil, penempatan Pencarian/Anotasi, dan penempatan Penampil secara bersamaan.
  3. Emit skrip untuk Penampil dan modul berlisensi.
  4. Muat viewerToolbar.js milik aplikasi host.
  5. Inisialisasi docViewer dan simpan objViewer yang dihasilkan.
  6. Inisialisasi setiap Pita Pencarian atau Anotasi berlisensi.
  7. Panggil attach(objViewer) pada setiap Pita.
  8. Buka dokumen dan simpan tokennya untuk permintaan Penampil dan modul.

Doconut.TestApp.Distributed mempertahankan komposisi UI persis ini serta pembantu bilah alat Penampil yang sama. Nilai permintaan access tambahan dan pengaturan ulang‑render asinkron milik transportasi terdistribusi; keduanya tidak mengubah cara Penampil, bilah alat, atau Pita disusun.

Pengaman sisi server penting: ketika kemampuan opsional tidak tersedia, skripnya tidak di‑emit, sehingga fungsi plugin jQuery tidak ada.

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>

Kedua komponen tersemat menghasilkan DOM Pita masing‑masing. Pencarian berisi grup Temukan, Opsi, dan Hasil. Anotasi berisi alat penulisan, kontrol gaya, aksi simpan, serta aksi ekspor/gambar opsional. Bilah‑bilah tersebut mengekspos open(), close(), reset(), dan isOpen(); selalu panggil attach(objViewer) sekali setelah membuatnya.

Contoh di atas menghilangkan callback host opsional dan endpoint ekspor/gambar Anotasi untuk menjaga startup tetap minimal. Lihat Pencarian dan Anotasi untuk penyiapan fitur lengkap, atau Tema Kustom untuk menata atau mengganti bilah alat Penampil milik host.

Buka dokumen

Sisi server hanya satu endpoint: layanan Viewer yang disuntikkan membuka dokumen dan mengembalikan token sesi.

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    // The token is opaque — hand it to the widget, never log or persist it.
    string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

Klien mengambil token itu dan memberikannya ke widget dengan objViewer.View(token):

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

Tutup dokumen

Panggil objViewer.Close() ketika pengguna meninggalkan penampil atau membuka dokumen pengganti. Pada alur kerja yang digerakkan server, viewer.CloseDocument(token) segera menghapus sesi cache, membuang mesin render, menghapus penanda keamanannya, dan mencabut token. Kedaluwarsa bergulir pada akhirnya melakukan pembersihan yang sama, tetapi penutupan eksplisit disarankan untuk dokumen berukuran besar.

Alur permintaan yang selesai adalah:

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

Perlakukan token seperti kredensial bearer: jangan pernah mencatatnya, jangan pernah menyimpannya, berikan hanya kepada widget. Token mengidentifikasi sesi dokumen hidup di server dan tidak akan berfungsi lagi ketika sesi tersebut kedaluwarsa — buka kembali dokumen untuk mendapatkan token baru.

Jalankan

Letakkan file PDF di wwwroot/files/Sample.pdf, jalankan dotnet run, dan buka halaman yang menampung widget. Halaman pertama akan dirender di penampil, dengan panel thumbnail di sebelah kiri. Jika tidak muncul, lihat Pemecahan Masalah.

Apa yang Anda dapatkan tanpa lisensi

Lisensi yang hilang tidak menyebabkan pengecualian. Penampil tetap merender secara normal, tetapi setiap halaman menampilkan watermark evaluasi. Lihat Penyiapan Lisensi untuk cara Doconut menemukan lisensi dan apa yang berubah setelah ditemukan.

Apakah halaman ini membantu?