Skip to content

Import and Export

David Benson edited this page Oct 7, 2026 · 1 revision

Every import and export format of the editor, the function that implements it, and whether it runs in the browser or needs a server. For developers who self-host (and must know what leaves the browser), debug an export, or call the conversions from their own code. Command-line export is part of the desktop app, see Desktop app.

Function names refer to js/diagramly/EditorUi.js and js/diagramly/Editor.js unless another file is named.

Overview

Format Import Export Runs
.drawio / .xml (mxfile, mxGraphModel, compressed or not) importXml, openLocalFile getFileData Browser
PNG / SVG / PDF with an embedded diagram Editor.extractGraphModelFromPng, Editor.extractGraphModel, Editor.extractGraphModelFromPdf Editor.writeGraphModelToPng, exportSvg, PDF via the export service Browser. PDF with an embedded copy needs an export service.
PNG, JPEG, WebP as images (importFiles) exportImage via Editor.prototype.exportToCanvas Browser. PNG and JPEG can also use the export service.
SVG as an image, or as a diagram if it has a content attribute exportSvg via Graph.prototype.getSvg Browser
PDF only PDFs with an embedded diagram print dialog, or the export service Browser print, or a server
HTML HTML containing a div.mxgraph createHtml Browser. The exported page loads the viewer script.
URL (#R link) App.prototype.loadFile createLink Browser
JSON (structure only) none createJsonForExport Browser
Animated GIF, MP4 none showAnimatedGifExportDialog (js/diagramly/gif/) Browser
Visio .vsdx, .vssx, .vstx importVisio → doImportVisio (vsdx/importer.js) not in this repository Browser
Visio .vsd, .vss, .vst (binary) importVisio → convertBinaryVisio none Browser if the DrawioVsd converter is loaded, otherwise VSS_CONVERT_URL
Visio .vdx, .vsx (XML 2003-2010) importVisio none Server only (VSS_CONVERT_URL)
Gliffy (.gliffy JSON or zip) importGliffy none Browser (js/gliffy/drawio-gliffy.min.js)
Lucidchart (JSON state, clipboard) convertLucidChart → LucidImporter (Extensions.js) none Browser
Mermaid parseMermaidDiagram Mermaid source kept in the cell Browser (bundle in extensions.min.js)
PlantUML parsePlantUmlDiagram PlantUML source kept in the cell Browser (js/plantuml/drawio-plantuml.min.js)
CSV with # configuration lines importCsv → doImportCsv none Browser
GraphML (yEd) importGraphML → mxGraphMlCodec (graphml/) none Browser
Miro (clipboard JSON) MiroImporter.importMiroJson (miro/) none Browser, paste only
Plain text, SQL CREATE TABLE ParseDialog (Dialogs.js) none Browser
Libraries (<mxlibrary>) loadLibrary saveLibrary Browser

The importers for Visio, Lucidchart, GraphML, Miro and Mermaid are compiled into js/extensions.min.js (the extensions part of the app target in etc/build/build.xml, see Building). PlantUML and Gliffy are separate bundles that are loaded on demand. Like the Mermaid, layout and routing bundles, they are built outside this repository and committed as minified files.

Servers are involved in only four cases:

  • PDF export with an export service configured, and the server-side PNG/JPEG fallback;
  • Visio formats the browser converter cannot read (VSS_CONVERT_URL);
  • File > Import from > URL, which fetches through PROXY_URL (the ProxyServlet at /proxy, which answers 404 unless the server environment sets ENABLE_DRAWIO_PROXY=1);
  • remote images and fonts in an export: Editor.prototype.createImageUrlConverter and mapFontUrl route other-origin URLs through the same proxy.

Export

The File > Export as menu

The menu exportAs in Menus.js adds these actions:

Item Action Shown when
PNG, JPEG, WebP exportPng, exportJpg, exportWebp editor.isExportToCanvas(). JPEG and WebP also need Editor.jpgSupported / Editor.webpSupported. Without canvas export, PNG and JPEG are offered if isRemoteExportEnabled().
Animation exportAnimatedGif canvas export
SVG exportSvg always
PDF exportPdf always (not in iOS standalone mode when an export service is used)
VSDX exportVsdx vsdxExportEnabled(), which is false in the app built from this repository
HTML, XML, URL, JSON exportHtml, exportXml, exportUrl (if Editor.enableExportUrl), exportJson always
Advanced... export → ExportDialog when online

File > Embed (createEmbedImage, createEmbedSvg, createHtml, createLink) uses the same functions. Copy as image and Copy as SVG use copyImage and copySvg.

SVG

Graph.prototype.getSvg (grapheditor/Graph.js, extended in diagramly/Editor.js for math and themes) creates an mxSvgCanvas2D and paints every cell state with mxImageExport, the same shapes as on screen. HTML labels become <foreignObject> elements. addForeignObjectWarning adds a <switch> fallback for viewers without foreignObject support. EditorUi.prototype.exportSvg adds the options of the export dialog: embedded images and fonts, links, theme, and the diagram copy in the content attribute. As the README says, SVG export is meant for embedding in web pages, not for editing in other tools.

PNG, JPEG and WebP

The raster formats are rendered from the SVG:

  1. Editor.prototype.exportToCanvas calls getSvg and inlines images with convertImages. It embeds fonts (embedExtFonts), draws the SVG data URI into a <canvas>, and passes the canvas on.
  2. EditorUi.prototype.exportImage → saveCanvas → createImageDataUri (canvas.toDataURL, plus the diagram chunk and DPI for PNG) → saveData, which downloads a Blob.

Editor.prototype.isExportToCanvas() is true when Editor.useCanvasForExport is. At start-up, the editor sets that flag by drawing a test SVG with a foreignObject to a canvas. If the browser cannot do that, PNG and JPEG are only offered through the export service. Editor.prototype.getMaxCanvasScale limits the canvas to 16384 pixels per side (8192 in Firefox) by reducing the scale.

Editable PNG and SVG

"Include a copy of my diagram" stores the mxfile in the image:

  • PNG: Editor.writeGraphModelToPng(data, 'tEXt', 'mxfile', encodeURIComponent(xml)) inserts a tEXt chunk before the first IDAT. Editor.extractGraphModelFromPng (grapheditor/Editor.js) reads tEXt and zTXt chunks with the keyword mxfile or mxGraphModel. Files named .drawio.png are saved this way automatically (getEmbeddedPng).
  • SVG: the content attribute of the root <svg> holds the mxfile, as plain, URI-encoded or base64 data. Editor.extractGraphModel reads it. .drawio.svg files use getEmbeddedSvg.

The details are in File format.

PDF

PDF has two paths, chosen by EditorUi.prototype.isPrintPdfExport(), which is printPdfExport || !isRemoteExportEnabled():

  • Print dialog (the default for builds from this repository). The public PreConfig.js sets window.EXPORT_URL = null, so isRemoteExportEnabled() is false. Export as > PDF opens the print dialog (showPrintDialog → PrintDialog → EditorUi.prototype.print), and the browser saves the PDF. No diagram data leaves the browser, but the PDF cannot contain a copy of the diagram. This is the behaviour described for the Docker image in Run a draw.io server with Docker.
  • Export service. If EXPORT_URL is an absolute http(s) URL or starts with /, downloadFile('pdf', ...) builds the request in downloadRequestBuilder and POSTs the diagram XML and options to it. Options include format, page range, scale, border, crop, transparent background and embedded copy. The service renders the diagram in a headless browser and returns the file. Requests are refused in the browser above MAX_AREA (15000 × 15000) or MAX_REQUEST_SIZE (10 MB).

EXPORT_URL is set only in PreConfig.js, never from a URL parameter. A link must not be able to redirect the diagram to someone else's server (advisory GHSA-ff67-v9r9-6877).

This repository does not contain an export service. It contains the parts one uses:

File Role
export3.html, js/export-init.js, js/export.js The render page: loads app.min.js and extensions.min.js. The headless browser calls render(data) with xml, csv or mermaid and the options. When the page is laid out, a hidden #LoadingComplete element carries the bounds, scale and page count for the driver. The desktop app uses the same page for its PDF and command-line export.
ExportProxyServlet.java, mapped to /export and /service/* Forwards a request to the URL in the server's EXPORT_URL environment variable, so the browser can use a same-origin window.EXPORT_URL = '/export'. Responses are capped at 100 MB.

The Node/Puppeteer reference service jgraph/draw-image-export2 is archived, and the docker-drawio README says the jgraph/export-server image has reached end of life. See Related repositories.

HTML, XML, URL and JSON

  • HTML: createHtml writes a <div class="mxgraph" data-mxgraph="..."> with the diagram and options, plus a <script> tag for the viewer: DRAWIO_VIEWER_URL if set, otherwise <DRAWIO_LIGHTBOX_URL>/js/viewer-static.min.js (default https://viewer.diagrams.net). A self-hosted deployment that must not depend on viewer.diagrams.net sets DRAWIO_VIEWER_URL. See Embed diagrams.
  • XML: downloadFile('xml') → getFileData, optionally compressed (Editor.defaultCompressed, configuration key compressXml).
  • URL: createLink creates #R + encodeURIComponent(Graph.compress(xml)). Graph.compress is pako.deflateRaw of the URI-encoded XML, base64-encoded. #R links open with App.prototype.loadFile, see Storage backends.
  • JSON: createJsonForExport(allPages, includeData, compressed, selection) writes the pages, cells and labels as JSON, optionally with the mxfile in a data field. There is no importer for this format.

Animations

showAnimatedGifExportDialog exports flow animations with AnimatedGifExport and step animations with AnimationExport. Output is a GIF (GifEncoder) or an MP4 (Mp4Encoder, which uses WebCodecs, gated by Mp4Encoder.isSupported()). All of it is in js/diagramly/gif/ and runs in the browser.

VSDX

EditorUi.prototype.exportVisio creates a VsdxExport, a class that is not part of this repository. The VSDX menu item is hidden unless vsdxExportEnabled() returns true, and in the app built from this repository it does not. The desktop command line does not export VSDX either.

Size limits

Constant Value Applies to
MAX_REQUEST_SIZE (grapheditor/Init.js) 10 MB Requests to the export service
MAX_AREA (grapheditor/Init.js) 15000 × 15000 Diagram bounds sent to the export service
Editor.prototype.getMaxCanvasScale 16384 px (8192 in Firefox) Canvas exports, by reducing the scale
EditorUi.prototype.maxCanvasExportArea 8192² px PNG exports through the embed protocol
EditorUi.prototype.maxPrintPageCount 1000 Print preview pages
EditorUi.prototype.maxImageBytes 2,000,000 Inserted images ("image too big" above this)
EditorUi.prototype.maxImageSize 1200 px Inserted images are scaled to fit (configuration maxImageSize)
EditorUi.prototype.maxTextBytes 500,000 Inserted text is truncated

Embed mode

An embedding application can request exports through the export action of the JSON protocol, in the formats png, xmlpng, svg, xmlsvg, html, html2, xml and json. The result comes back in an export message instead of a download. See Embedding and the embed mode reference.

Import

Open, import, insert

Entry Function Behaviour
File > Open, opening a file dropped on an empty diagram openFiles → openLocalFile Replaces the current file. Detects Visio, GraphML, Gliffy, Lucidchart and libraries, and extracts the diagram from PNG and PDF.
File > Import from > Device importLocalFile(true) → importFiles Adds to the current diagram
File > Import from > URL PROXY_URL + '?url=' + url → importFile Adds to the current diagram
Drop on the canvas drop listener on graph.container → importFiles, or extractGraphModelFromEvent for text and HTML Adds at the drop position. Shift-drop, or one .drawio/.xml/Visio file dropped on a blank diagram, opens it instead.
Drop on the page outside the canvas addFileDropHandler (installed by App) Opens the files
Paste pasteCells → pasteXml, pasteFromClipboard See below

importFiles(files, x, y, ...) reads each File:

  • SVG with an mxfile in content is imported as a diagram; other SVGs become image cells.
  • PNG with an embedded diagram is imported as a diagram; other images become image cells. Images are resized above maxImageSize, and Editor.removeImageMetadata can strip EXIF data.
  • Visio files go to importVisio.
  • PDFs are read as data URLs and passed to insertTextAt, which calls Editor.extractGraphModelFromPdf.
  • Everything else is read as text and passed to importFile.

importFile(data, mimeType, ...) checks, in this order:

  1. a library (<mxlibrary>, loaded with loadLibrary);
  2. an image, or a PNG with an embedded diagram;
  3. <graphml → importGraphML;
  4. a Visio file name → importVisio;
  5. Gliffy data (isGliffyData) → importGliffy;
  6. a zip archive (PK) → importZipFile, which takes diagram/diagram.xml from a draw.io zip or the latest versions/ entry of a Gliffy archive;
  7. anything else → insertTextAt.

insertTextAt handles PNG, PDF and SVG data URIs. It sends draw.io XML (isCompatibleString) to importXml and Lucidchart JSON (isLucidChartData) to convertLucidChart. Other text becomes a text cell, sanitised and truncated at maxTextBytes. importXml(xml, dx, dy, crop, ...) does the actual insert: a multi-page mxfile adds pages, a single page is merged into the current page.

Paste. pasteCells recognises, in order:

  • Lucidchart clipboard HTML (data-lucid-type="application/vnd.lucid.chart.objects") → convertLucidChart;
  • draw.io XML, also URI-encoded;
  • Miro clipboard JSON (starting with {"isProtected":) → MiroImporter;
  • files on the clipboard → importFiles.

Anything else goes to pasteXml. The asynchronous Clipboard API path is pasteFromClipboard → readGraphModelFromClipboard.

Visio

importVisio(file, done, error, filename) loads extensions.min.js if needed:

  • .vsdx, .vssx and .vstx are unzipped (JSZip) and converted in the browser by mxVsdxCodec (diagrams) or mxVssxCodec (stencils, which become a library), in vsdx/importer.js. Embedded EMF images go through emfToSvg (emf/emf-svg.js), BMP images through BmpDecoder (vsdx/bmpDecoder.js).
  • .vsd, .vss and .vst are converted in the browser by convertBinaryVisio when the DrawioVsd converter (js/vsd/drawio-vsd.min.js, appended to extensions.min.js by the build) is loaded and can read the file.
  • Otherwise, and for .vdx and .vsx (isRemoteVisioFormat), the file is POSTed to VSS_CONVERT_URL. That defaults to a conversion service on convert.diagrams.net (diagramly/Init.js) and is skipped when the editor is offline.

Init.js sets the default with ||, so a null in PreConfig.js does not disable it. A deployment that must never send files there sets window.VSS_CONVERT_URL = null; in PostConfig.js, which loads after the app, or runs with offline=1.

vsdxImporter.html with js/vsdxImporter.js is a headless page around importVisio. The desktop command line uses it for Visio input.

Gliffy and Lucidchart

  • Gliffy: importGliffy → loadGliffy (loads js/gliffy/drawio-gliffy.min.js) → mxGliffyToDrawio.convert(data). It accepts Gliffy JSON ("contentType":"application/gliffy+json") and Gliffy zip archives.
  • Lucidchart: convertLucidChart → LucidImporter.importState, in Extensions.js. The input is Lucidchart's JSON document state (isLucidChartData), typically from the clipboard. It is not a .lucid file.

End-user steps: Lucidchart import, Gliffy import, import formats.

Mermaid, PlantUML, text and SQL

Arrange > Insert > Advanced (and Insert > Mermaid) open ParseDialog (Dialogs.js). Its types are:

Type Converter
mermaid (editable shapes), mermaidImage parseMermaidDiagram / parseMermaidImage, using mxMermaidToDrawio from the Mermaid bundle in extensions.min.js. Available when EditorUi.isMermaidSupported(), which needs structuredClone.
plantUmlDiagram, plantUmlImage parsePlantUmlDiagram / parsePlantUmlImage, using mxPlantUmlToDrawio from js/plantuml/drawio-plantuml.min.js
list Class-like blocks of text become list shapes
diagram, circle, horizontalFlow, verticalFlow One edge per line, a->b or a->label->b, laid out with the chosen layout. Lines starting with ; are ignored.
table CREATE TABLE statements become table shapes

Mermaid and PlantUML run entirely in the browser; no rendering server is involved. The generated cells keep the source in the mermaidData or plantUmlData attribute, so the diagram can be edited and regenerated. User documentation: Mermaid, PlantUML, from text.

CSV

Arrange > Insert > Advanced > CSV → showImportCsvDialog → importCsv → doImportCsv. The input is CSV data preceded by # lines that configure labels, styles, connections, placement and layout. doImportCsv creates or, with an identity column, updates the cells inside one model transaction, so one undo reverts the import. An org-chart layout loads its scripts (loadOrgChartLayouts) first. The format is documented at Insert from CSV. The same code runs headless in export.js when an export request carries csv.

GraphML, Miro and libraries

  • GraphML (yEd): importGraphML → mxGraphMlCodec.decode (graphml/mxGraphMlCodec.js). Import only.
  • Miro: clipboard JSON copied from a Miro board, converted by MiroImporter.importMiroJson (miro/MiroImporter.js). Paste only.
  • Libraries: <mxlibrary> files open as a sidebar library (loadLibrary), not as a diagram. See Shapes and stencils.

The plugins import.js (p=import, Freemind) and sql.js (p=sql) add more importers, see Plugins.

See also

Clone this wiki locally