Anotace
Přidejte podporu anotací do prohlížeče
Anotace v Doconut fungují ve dvou směrech: uživatelé je kreslí ve widgetu prohlížeče a server je ukládá po stránkách, nebo je váš kód vytváří a načítá do otevřené relace. V každém případě se vykreslují na stránkách a mohou být vloženy do exportů PDF nebo PNG.
Podpora anotací je řízena licenční schopností Annotation (udělenou automaticky při aktivní dočasné licenci).
Povolení uživatelského rozhraní anotací
Anotace jsou modulem Vieweru, nikoli samostatným nástrojovým panelem. Stránka musí zahrnovat zdroje Vieweru, nástrojový panel Vieweru, umístění Vieweru a inicializovaný objViewer; poté je pás Anotací namontován a připojen k téže instanci.
Vydávejte soubory anotací spolu se soubory vieweru. Jsou řízeny licencí, takže jejich značky se zobrazí pouze když je schopnost udělena. V MVC 5 vytvořte značky v kontroleru (pohledy nemají @inject):
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
ViewBag.ViewerCss = viewer.ReferenceCss(new CssConfig
{
IncludeViewerCss = true,
IncludeAnnotationCss = true // jquery-ui.min.css + annotationBar.css
});
ViewBag.ViewerScripts = viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeViewerScripts = true,
IncludeAnnotationScripts = true, // jquery-ui, raphael.js, annotation.js
IncludeAnnotationBar = true // the embedded annotation ribbon
});
ViewBag.IsAnnotationEnabled = viewer.IsAnnotationEnabled;Uchovejte kompletní složení Vieweru v markupu:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Ovládací prvky Vieweru, včetně tlačítka, které otevírá Anotaci -->
</nav>
<div id="annBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>Souborů anotací generují pás uvnitř annBarMount; nekopírujte jeho tlačítka ani dialogy. Nejprve inicializujte docViewer, pak vytvořte pás pouze když server potvrdí, že anotace jsou licencovány:
@Html.Raw(ViewBag.ViewerScripts)
<script>
var annBar = null;
var currentToken = '';
var objViewer = $('#div_ctlDoc').docViewer({
BasePath: '/',
ResPath: 'doconut-res/images',
onAnnLoaded: function () { if (annBar) annBar.handleAnnLoaded(); },
onAnnSaved: function () { if (annBar) annBar.handleAnnSaved(); },
onAnnSaveError: function () { if (annBar) annBar.handleAnnSaveError(); },
onAnnClosed: function () { if (annBar) annBar.handleAnnClosed(); },
onError: function (message) { console.error('Viewer error:', message); }
});
@if ((bool)ViewBag.IsAnnotationEnabled)
{
<text>
annBar = $('#annBarMount').doconutAnnotationBar({
docId: 'ctlDoc',
getRequestParams: function () { return { token: currentToken }; },
onLayout: function () { requestAnimationFrame(function () { objViewer.Refit(); }); }
});
annBar.attach(objViewer);
</text>
}
</script>Bez této schopnosti ReferenceScripts vynechá skript pásu, takže podmínka na straně serveru if chrání nechráněné volání doconutAnnotationBar(...) před rozbitím stránky. Ve Web Forms napište stejnou ochranu jako <% if (IsAnnotationEnabled) { %> … <% } %>.
Ukládání z pásu odesílá data na DocImage.axd (AnnSave), který je ukládá v relaci dokumentu po stránkách. Načítání (AnnLoad) probíhá automaticky, když se vykreslí stránka s anotacemi.
Otevřete a zavřete pás z vlastního nástrojového panelu pomocí annBar.open() a annBar.close(). Jeho veřejné API:
| Metoda | Účel |
|---|---|
attach(objViewer) | Připojí pás k inicializovanému vieweru; vyžadováno jednou |
open() / close() | Vstoupit do nebo opustit režim úprav anotací |
reset() | Vrátí pás do zavřeného, needitačního stavu |
isOpen() / annotating() | Přečte stav pásu / stav úprav anotací ve vieweru |
reopenEditable() | Znovu načte anotace aktuální stránky jako editovatelné objekty |
updateActionState() | Obnoví ovládací prvky pro uložení a smazání po změnách hosta |
headerSlot() | Volitelný slot hlavičky pro ovládací prvky vlastněné hostem |
onStatus, onToast, onLayout, onEditStart a onEditEnd jsou volitelné zpětné volání hosta. Objekt endpoints může také poskytovat exportPdf, exportPng, imageUpload a imageList; ovládací prvky bez nastaveného koncového bodu zůstávají skryté.
Dva typy zpětných volání, zapojené dvěma způsoby
Kód anotací používá dva styly zpětných volání a každý selže tiše, když je zapojen opačným způsobem:
onAnnLoaded,onAnnSaved,onAnnSaveError,onAnnClosedjsou volbydocViewer({...}), jako každé zpětné volání prohlížeče.Created,Changed,DeletedaPropertiesjsou globální funkce nalezené podle názvu: ID prohlížeče je předponou události. Pro prohlížeč v#div_ctlDocje IDctlDoc, takže funkce jsouctlDoc_Created,ctlDoc_Changed,ctlDoc_DeletedactlDoc_Properties. Špatně napsaná nebo přejmenovaná funkce prostě není nikdy zavolána.
SaveAnnotations() nevrací, zda se uložilo: výsledek přichází přes onAnnSaved nebo onAnnSaveError. Kód, který čte její návratovou hodnotu, nikdy neodstraní příznak „neuložených změn“.
Vytváření anotací v C#
Získejte správce svázaného s otevřenou relací, přidejte anotace a načtěte je (s using Doconut.Annotations; pro typy a using System.Drawing; pro Rectangle a Color):
// POST /Annotations/LoadSample?token=...
[HttpPost]
public ActionResult LoadSample(string token)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
// Bound to the open session's page dimensions
var manager = viewer.GetAnnotationManager(token);
var pageCount = viewer.GetPageCount(token);
// One stamp per page
for (int page = 1; page <= pageCount; page++)
{
manager.Add(new StampAnnotation(page, new Rectangle(30, 20, 240, 90),
$"PAGE {page}", 28, 4, Color.Maroon)
{
Opacity = 60,
Rotate = -8
});
}
manager.Add(new NoteAnnotation(1, new Rectangle(420, 150, 220, 120),
"Loaded from C# code.", Color.FromArgb(255, 255, 255, 170), 14));
// Load into the session - the viewer fetches them, and the renderer burns them into
// image/PDF exports.
viewer.LoadAnnotationData(token, manager);
return new HttpStatusCodeResult(200);
}Typy anotací
Všechny typy jsou v Doconut.Annotations a dědí z BaseAnnotation (číslo stránky plus ohraničující Rectangle):
| Typ | Poznámky |
|---|---|
StampAnnotation | Textová razítko s velikostí písma, okrajem, barvou; podporuje Opacity, Rotate |
NoteAnnotation | Lepící poznámka s textem, barvou pozadí, velikostí písma, TitleColor |
RectangleAnnotation | Barvy okraje a výplně, Title/ShowTitle |
CircleAnnotation | Okraj a výplň, ShowBorder |
EllipseAnnotation | Okraj a výplň, ShowBorder |
TriangleAnnotation | Barva okraje, BackColor, ShowBorder |
LineAnnotation | Přímka s šířkou a barvou |
ArrowAnnotation | Čára s šipkou; nastavitelný Direction (ArrowDirection, směry kompasu, výchozí E) |
FreehandAnnotation | Volná čára z kódovaných bodů FreehandData |
ImageAnnotation | Obrázek z URL. Relativní URL je vyřešena vůči hostiteli aktuálního požadavku, když je anotace přidána — viz poznámka o exportu níže |
API AnnotationManageru
| Člen | Účel |
|---|---|
Add(BaseAnnotation) | Přidá anotaci do fronty |
GetAnnotations() / GetAnnotations(int page) | Prohlédne, co správce obsahuje |
ClearAnnotations() / ClearAnnotations(int page) | Odstraní všechny / podle stránky |
GetAnnotationData() / GetAnnotationData(int page) | Kódovaná data anotací — obálka, kterou widget spotřebuje |
GetAnnotationXml() | XML forma |
Viewer zrcadlí operace načítání a čtení vůči relaci: LoadAnnotationData(token, manager) nebo LoadAnnotationData(token, encodedData), LoadAnnotationXML(token, xml) a GetAnnotationXML(token).
Export s vloženými anotacemi
// PDF of all pages with annotations rendered onto them
public async Task<ActionResult> ExportPdf(string token)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
byte[] pdf = await viewer.ExportAnnotationsToPdfAsync(token, zoom: 100, ct: Response.ClientDisconnectedToken);
return File(pdf, "application/pdf", "export.pdf");
}
// Or a ZIP of per-page PNGs
public async Task<ActionResult> ExportPngZip(string token)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
byte[] zip = await viewer.ExportAnnotationsToPngZipAsync(token, zoom: 100, ct: Response.ClientDisconnectedToken);
return File(zip, "application/zip", "annotations-png.zip");
}Exporty používají stejný proces vypalování jako vykreslování na obrazovce a stejná rozhodnutí o licenci a vlastním vodoznaku.
Anotace obrázků na intranetovém hostiteli exportují jako „Image blocked“
Prohlížeč a export získávají obrázek ImageAnnotation z různých míst:
| Rozhraní | Kdo stahuje obrázek | Na intranetovém nebo vývojovém hostiteli |
|---|---|---|
| Prohlížeč v prohlížeči | Prohlížeč uživatele | Obrázek se zobrazí |
ExportAnnotationsToPdfAsync / …PngZipAsync | Server | Červený "Image blocked" zástupný obrázek |
Když server načte obrázek, aby jej vložil, odmítá adresy, které směřují zpět do soukromých sítí: smyčkovou (localhost, 127.0.0.1), 0.0.0.0, link‑local (169.254.x.x), soukromé rozsahy 10.x, 172.16–31.x a 192.168.x, carrier‑grade NAT (100.64.0.0/10) a IPv6 link‑local a unique‑local adresy. To chrání server před použitím k přístupu k interním systémům prostřednictvím upravené URL obrázku a neexistuje žádný přepínač, který by to vypnul.
Relativní URL obrázku se rozřeší vůči hostiteli aktuálního požadavku, takže na localhost, na intranetovém serveru nebo na jakémkoli webu dosažitelém přes soukromou adresu se obrázek zobrazí v prohlížeči a export místo toho obsahuje zástupný obrázek. To je fungující ochrana, ne selhání vykreslování. Pokud exporty musí obsahovat obrázek, poskytujte jej z hostitele s veřejnou adresou a použijte absolutní URL. URL obrázku, kterou nelze vůbec rozřešit, způsobí, že se daná anotace ztratí bez chyby — zkontrolujte vykreslené pixely nebo síťový log, ne stavový kód.
Pracovní postup uchovávání
- Otevřete dokument a získejte jeho token.
- Načtěte dříve uložené XML nebo kódovaná data do tohoto tokenu.
- Nechte widget načíst a upravit anotace relace.
- Získejte XML pomocí
GetAnnotationXML(token), když se vaše aplikace rozhodne data uložit. - Exportujte PDF nebo PNG, když je vyžadován plochý výstup.
- Ukončete relaci dokumentu.
Neužívejte token prohlížeče jako trvalý identifikátor anotace — zaniká s relací a recyklace aplikačního poolu ukončí každou relaci na jednom serveru. Ukládejte data anotací pod své vlastní identifikátory dokumentu a verze.
Poznámky o zabezpečení a vykreslování
- Požadavky na anotace používají stejnou bezpečnost relace a tokenu jako požadavky na stránky.
- Ověřujte a kontrolujte jakoukoli uživatelem dodanou URL obrázku.
- Velké volné kresby a exporty ve vysokém rozlišení zvyšují spotřebu paměti; testujte realistické dokumenty a hodnoty přiblížení.
Odstraňování potíží
| Příznak | Kontrola |
|---|---|
| Chybí páska Anotace | Annotation schopnost a čtyři CSS/script příznaky anotací |
| Ukládání hlásí chybu | Vypršení tokenu nebo relace a BasePath widgetu |
ctlDoc_Created (nebo jiná funkce události) se nikdy nespustí | Název funkce: id prohlížeče + _ + událost, jako globální funkce |
| Anotace v C# se neobjeví | Čísla stránek jsou od jedné a data byla načtena do aktivního tokenu |
| Anotace obrázku se zobrazuje na obrazovce, ale ne v exportu | Hostitel obrázku má soukromou nebo smyčkovou adresu — viz výše |
| Znovu otevřený dokument nemá žádné anotace | Uložte XML nebo data mimo relaci prohlížeče a poté je načtěte do nového tokenu |
Byla tato stránka užitečná?