Data-URI-Generator
Kodiere ein Bild, eine Schrift oder Text als data: URI oder dekodiere einen — mit Base64 und Prozentkodierung gegeneinander gemessen. Läuft im Browser.
data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232563eb'%20stroke-width='2'%3E%3Ccircle%20cx='12'%20cy='12'%20r='9'/%3E%3Cpath%20d='M8%2012.5l2.5%202.5%205-6'/%3E%3C/svg%3E
Hier ist die Prozentkodierung kürzer: 255 Zeichen gegenüber 272, 17 gespart.
Größen
- Bytes der Quelle
- 174
- URI, Base64
- 272
- URI, prozentkodiert
- 255
Eine Datei in einer Adresse
Ein Data-URI ist eine ganze Datei, ausgeschrieben als Adresse. Statt auf eine Ressource zu zeigen, die der Browser erst holen muss, trägt er die Bytes selbst — ein Symbol kann so in dem Stylesheet wohnen, das es benutzt, und ein kleines Bild in dem HTML, das es zeigt. RFC 2397 hat das Schema 1998 definiert, und seit zwei Jahrzehnten wird es überall unterstützt.
Die Grammatik ist kurz. Nach dem Schema folgen ein optionaler Medientyp mit optionalen Parametern, dann eine optionale base64-Markierung, dann ein Komma, dann die Daten. Alles vor dem Komma ist der Kopf, alles danach sind die Nutzdaten — deshalb trennt der Browser am ersten Komma, und deshalb ist ein Komma in den Nutzdaten harmlos.
data:[<mediatype>][;base64],<data> data:,hello text/plain;charset=US-ASCII data:text/plain;charset=utf-8,hello the same bytes, spelled out data:image/png;base64,iVBORw0KGgo= binary, Base64 encoded data:image/svg+xml,%3Csvg%20... markup, percent-encoded
Ein leerer Kopf ist zulässig und bedeutet text/plain;charset=US-ASCII — der einzige Vorgabewert, den die Spezifikation mitliefert. Diese Seite meldet, dass sie ihn angewandt hat, statt einen Medientyp anzuzeigen, den Sie nie geschrieben haben.
Zwei Kodierungen, und welche kürzer ist
Der RFC definiert zwei Arten, die Nutzdaten zu schreiben, und die Wahl ist keine Stilfrage: Für eine konkrete Datei ist eine davon deutlich kürzer, und welche das ist, hängt vollständig vom Inhalt der Datei ab.
Base64 schreibt je drei Bytes als vier Zeichen aus einem Alphabet von 64 um. Der Preis ist fest und vorhersehbar: genau ein Drittel mehr, plus Auffüllung. Es funktioniert für alles, weshalb man von Haus aus danach greift.
Prozentkodierung lässt jedes in einer URL zulässige Zeichen genau so stehen und gibt für jedes andere drei Zeichen aus. Bei Nutzdaten, die überwiegend aus schlichtem ASCII bestehen — ein SVG, ein kleines Stylesheet, ein Stück JSON —, gehen die meisten Bytes unangetastet durch, und das Ergebnis fällt kürzer aus als Base64, oft um zwanzig bis dreißig Prozent. Bei einem PNG oder einer Schrift, wo fast jedes Byte maskiert werden muss, nähert es sich dem Dreifachen des Originals und ist damit weit schlechter als Base64.
Wie viel maskiert wird, ist selbst eine Entscheidung, und diese Seite bietet beide Antworten:
- Der strenge Satz maskiert jedes Byte außerhalb der nicht reservierten Zeichen von RFC 3986 — Buchstaben, Ziffern, Bindestrich, Punkt, Unterstrich und Tilde. Das Ergebnis ist in jedem Kontext sicher, um den Preis, auch Satzzeichen zu maskieren, die es nicht nötig hatten.
- Der minimale Satz behält alles, was die Grammatik des Data-URI tatsächlich erlaubt, einschließlich Schrägstrichen, Doppelpunkten, Gleichheitszeichen, Anführungszeichen und Klammern, von denen Auszeichnungssprache voll ist. Hier gewinnt die Prozentkodierung, und deshalb kodiert ein SVG mit einfachen Anführungszeichen um seine Attribute weit besser als eines mit doppelten.
- Das Ziel fügt eine weitere Regel hinzu. In einem HTML-Attribut beginnt ein nacktes Kaufmanns-Und eine Zeichenreferenz, deshalb maskiert die Wahl des img-Ziels auch dieses. Sonst ändert sich nichts: Das doppelte Anführungszeichen, die spitzen Klammern und der Rückstrich liegen ohnehin außerhalb des erlaubten Satzes und werden auf beiden Stufen maskiert.
- Das Prozentzeichen wird immer maskiert, auf jeder Stufe. Es leitet eine Escape-Sequenz ein, ein wörtliches Prozent muss also als %25 geschrieben werden, sonst werden die beiden folgenden Zeichen als Hexadezimalziffern gelesen.
Statt Sie raten zu lassen, kodiert die Seite die Nutzdaten auf beide Arten und nennt beide Längen und den Unterschied. Nehmen Sie den Gewinner, oder setzen Sie die Kodierung von Hand, wenn Sie einen Grund haben.
Die 33 % sind eine Zahl vor der Kompression
Fast jede Diskussion über Data-URIs wiederholt, dass Base64 ein Drittel zur Dateigröße hinzufügt. Rechnerisch stimmt das und praktisch führt es in die Irre, denn die Zahl beschreibt die Bytes, bevor sie auf die Leitung gehen, und jeder Server komprimiert Text beim Ausliefern.
Base64 fügt keine Information hinzu; es verteilt dieselbe Information auf mehr Zeichen und nutzt nur 64 der 256 Werte, die ein Byte annehmen kann. Genau diese Redundanz zu entfernen ist der Daseinszweck von gzip und Brotli. Bei bereits komprimierten Nutzdaten — einem PNG, einem JPEG, einer WOFF2-Schrift — kommt der Kompressor an die eigentlichen Daten nicht heran, kann aber das Base64 wieder auf nahezu die ursprüngliche Größe packen. Das berühmte Drittel verschwindet größtenteils.
Deshalb misst diese Seite, statt zu behaupten. Sie komprimiert drei Dinge mit der gzip-Implementierung des Browsers: die Nutzdaten so, wie sie als eigene Datei ausgeliefert würden, das Dokument, das sie als Base64 trägt, und das Dokument, das sie prozentkodiert trägt. Diese drei Zahlen sind die ehrliche Fassung des Größenarguments, und sie zeigen oft, dass der wahre Preis des Einbettens gar nicht die Größe ist.
Die wahren Kosten liegen anderswo. Eine eingebettete Datei lässt sich nicht für sich zwischenspeichern, wird also mit jeder Kopie des tragenden Dokuments erneut geladen und niemals zwischen zwei Seiten geteilt. Sie blockiert außerdem: Ein Stylesheet wird nicht fertig geparst, bevor es den mittendrin sitzenden URI ganz gelesen hat. HTTP/2 hat den größten Teil der Kosten pro Anfrage beseitigt, die das Einbetten überhaupt erst attraktiv machten. Für ein winziges Symbol auf jeder Seite bleibt es ein vernünftiger Tausch; jenseits einiger zehn Kilobyte meist nicht, und deshalb warnt diese Seite ab dreißig.
Der Typ kommt aus den Bytes
Ein Data-URI nützt nur, wenn der Medientyp stimmt. Stimmt er nicht, weigert sich der Browser, das Bild anzuzeigen, wendet den falschen Parser an oder bietet — bei allem, was mit einem ihm unbekannten Typ ausgeliefert wird — stattdessen einen Download an.
Wenn Sie eine Datei ablegen, meldet der Browser einen eigenen Typ, doch diese Meldung stammt allein aus der Dateiendung. Benennen Sie ein JPEG in .png um, und der Browser nennt es PNG. Diese Seite liest stattdessen die ersten Bytes. Fast jedes Binärformat beginnt mit einer Signatur: PNG mit einem Byte, das in ASCII nicht vorkommen kann, gefolgt von den Buchstaben PNG; JPEG mit drei festen Bytes; PDF mit einem Prozentzeichen und dem Wort PDF; WOFF und WOFF2 mit ihren eigenen vier Zeichen langen Kennungen. Widersprechen sich Signatur und Endung, gewinnt die Signatur, und der Widerspruch wird gemeldet.
Die Liste ist bewusst kurz — die Formate, die tatsächlich eingebettet werden, nicht alles, was ein Browser erschnüffeln kann. Passt nichts und sind die Bytes gültiger Text, ist der Typ Text, wobei SVG und XML danach unterschieden werden, womit die Auszeichnung beginnt. Passt gar nichts, lautet die Antwort application/octet-stream, und das Feld bleibt bearbeitbar, denn eine falsche Vermutung ist schlimmer als eine eingestandene.
Bei textuellen Nutzdaten zählt auch der Zeichensatz. Die Vorgabe der Spezifikation ist US-ASCII, was heute niemand meint, deshalb wird ein Text-Medientyp mit angehängtem charset=utf-8 angeboten. Ihn wegzulassen beschädigt die Bytes nicht, ändert aber, wie sie wieder gelesen werden.
Einen wieder auslesen
Die andere Hälfte der Arbeit kommt häufiger vor: Sie haben einen data: URI in einem Stylesheet, einem DOM-Auszug oder einer gespeicherten Seite gefunden und wollen wissen, was er ist. Fügen Sie ihn ein, und die Seite nimmt ihn auseinander — den Medientyp, seine Parameter, welche Kodierung verwendet wurde, zu wie vielen Bytes er dekodiert gegenüber wie vielen Zeichen er kostet, und was diese Bytes unabhängig von der Behauptung des Kopfes sind. Ein Bild wird gezeichnet, Text wird angezeigt, alles andere bekommt seine ersten Bytes in Hexadezimal.
Das Dekodieren ist streng, denn ein eingefügter URI ist nicht vertrauenswürdige Eingabe, und eine plausible falsche Antwort ist schlimmer als ein Fehler. Ein fehlendes Komma, ein kaputter Medientyp, ein Prozentzeichen ohne zwei Hexziffern, ein Zeichen außerhalb des Base64-Alphabets: Jeder Fall scheitert mit der Position des Problems, statt still repariert zu werden.
Zwei Dinge werden geduldet, weil jeder Browser sie duldet und ein aus einem umbrochenen Stylesheet kopierter URI sonst unbrauchbar wäre. Leerraum in den Nutzdaten wird entfernt, fehlende Base64-Auffüllung wird ergänzt. Beides wird gemeldet, damit Sie wissen: Der URI, den Sie haben, ist nicht ganz der URI, der überall funktioniert.
Eine ähnlich aussehende Sache wird rundheraus abgelehnt. Das URL-sichere Base64-Alphabet, das Plus und Schrägstrich durch Bindestrich und Unterstrich ersetzt, verwenden JSON Web Token — und es ist nicht das, was ein Data-URI annimmt. Es stillschweigend zu akzeptieren hieße, zu anderen Bytes zu dekodieren als der Browser, deshalb wird es namentlich abgelehnt, mit der Position des störenden Zeichens.
Wo das läuft
Alles geschieht in Ihrem Browser. Die gewählte Datei wird mit der lokalen Datei-Schnittstelle gelesen und nie hochgeladen; Kodierung, Kompressionsmessung und Dekodierung laufen auf Ihrem eigenen Rechner, und nichts wird gespeichert oder protokolliert. Das zählt hier mehr als auf den meisten Seiten, denn die Dateien, die man in Data-URIs verwandelt, sind oft interne Ressourcen, und die URIs, die man zur Prüfung einfügt, stammen aus Produktivseiten.
Häufig gestellte Fragen
- Wird meine Datei irgendwohin hochgeladen?
- Nein. Die Datei wird lokal mit der Datei-Schnittstelle des Browsers gelesen, auf Ihrem Rechner kodiert und nirgendwohin gesendet. Dasselbe gilt für einen URI, den Sie zum Dekodieren einfügen.
- Soll ich Base64 oder Prozentkodierung verwenden?
- Was für Ihre Daten kürzer ist — und genau das misst die Seite für Sie. Als Faustregel: Prozentkodierung für SVG, CSS, JSON und anderen Text, Base64 für Bilder, Schriften und alles bereits Komprimierte. Der Unterschied beträgt oft zwanzig bis dreißig Prozent in die eine oder andere Richtung.
- Macht Base64 eine Datei wirklich 33 % größer?
- Vor der Kompression ja: vier Zeichen je drei Bytes. Auf der Leitung größtenteils nicht. Base64 nutzt nur 64 der 256 möglichen Bytewerte, und genau diese Redundanz entfernt gzip, sodass die komprimierte Größe meist nahe an der komprimierten Größe der Originaldatei liegt. Die Seite misst beides, damit Sie es sehen.
- Wie groß darf ein Data-URI sein?
- Moderne Browser setzen für einen URI in einem Dokument keine harte Grenze, auch wenn alte Internet-Explorer-Versionen bei 32 KB abschnitten. Die Größe ist eine Leistungs- und keine Rechtsfrage: Eine eingebettete Datei lässt sich nicht getrennt zwischenspeichern und wird mit jeder Kopie des Dokuments neu geladen. Diese Seite kodiert bis zu einem Megabyte und warnt ab dreißig Kilobyte.
- Warum bricht mein SVG-Data-URI in CSS?
- Fast immer wegen eines nicht maskierten Zeichens. Ein Rautezeichen — etwa aus einer Farbe wie #2563eb — beginnt einen Fragmentbezeichner und schneidet den URI an dieser Stelle ab. Ein doppeltes Anführungszeichen beendet die CSS-Zeichenkette, in der es steht. Schreiben Sie das SVG mit einfachen Anführungszeichen um die Attribute und nehmen Sie den minimalen Escape-Satz: Er maskiert Raute und doppeltes Anführungszeichen und lässt alles andere kurz.
- Kann ich einen Data-URI für ein Skript oder ein iframe verwenden?
- Können schon, aber behandeln Sie es als Sicherheits- und nicht als Bequemlichkeitsfrage. Ein Data-URI erbt keinen Ursprung, und Browser blockieren genau deshalb bereits die Navigation der obersten Ebene dorthin. Eine Content-Security-Policy, die data: in script-src oder frame-src erlaubt, gibt das meiste von dem preis, was die Richtlinie schützen sollte; es in img-src oder font-src zu erlauben, ist alltäglich.
- Warum wurde mein URL-sicheres Base64 abgelehnt?
- Weil ein Data-URI Standard-Base64 annimmt. Das URL-sichere Alphabet tauscht Plus und Schrägstrich gegen Bindestrich und Unterstrich — andere Zeichen, die zu anderen Bytes dekodieren. Es anzunehmen hieße, dass diese Seite Ihren URI anders dekodiert als der Browser, der ihn tatsächlich lädt.
- Der Browser nennt einen Typ, diese Seite einen anderen. Wer hat recht?
- Die Seite. Ein Browser meldet den aus der Dateiendung abgeleiteten Typ und liegt bei einer umbenannten Datei falsch. Diese Seite liest die Signatur am Dateianfang, also das, was das Format selbst erklärt. Das Feld bleibt bearbeitbar, falls Sie einen Grund haben, es zu überschreiben.