Frage

Ich erhalte einige XML-Dateien mit eingebetteten Base64-codierten Bildern, die ich zu dekodieren muß und als Dateien speichern.

Eine unverändert (außer gezippt) Beispiel für eine solche Datei kann hier heruntergeladen werden:

20091123-125320.zip (60KB)

Allerdings bekomme ich Fehler wie „Ungültige Länge für einen Base-64-char-Array“ und „Ungültige Zeichen in einem Base-64-string“. Ich markierte die Zeile im Code, wo ich den Fehler im Code zu erhalten.

Eine Datei könnte wie folgt aussehen:

<?xml version="1.0" encoding="windows-1252"?>
<mediafiles>
    <media media-type="image">
      <media-reference mime-type="image/jpeg"/>
      <media-object encoding="base64"><![CDATA[/9j/4AAQ[...snip...]P4Vm9zOR//Z=]]></media-object>
      <media.caption>What up</media.caption>
    </media>
</mediafiles>

Und der Code-Prozess wie folgt aus:

var xd = new XmlDocument();
xd.Load(filename);
var nodes = xd.GetElementsByTagName("media");

foreach (XmlNode node in nodes)
        {
            var mediaObjectNode = node.SelectSingleNode("media-object");
            //The line below is where the errors occur
            byte[] imageBytes = Convert.FromBase64String(mediaObjectNode.InnerText);
            //Do stuff with the bytearray to save the image
        }

Die XML-Daten aus einem Unternehmen Zeitung System, so bin ich ziemlich sicher, dass die Dateien sind ok - und es muss etwas in der Art und Weise, die ich sie verarbeiten, die einfach falsch ist. Vielleicht ein Problem mit der Codierung?

Ich habe versucht, den Inhalt mediaObjectNode.InnerText auszuschreiben, und es ist die Base64-codierten Daten -. So das die XML-doc Navigation ist nicht das Problem

Ich habe googeln, binging, stackoverflowing und weinen - und fand keine Lösung ... Hilfe

Edit:

Hinzugefügt ein tatsächliches Beispieldatei (und eine Prämie). Bitte beachten Sie die herunterladbare Datei in einem etwas anderen Schema ist, da ich es in dem obigen Beispiel vereinfachte, Entfernen von irrelevanten Sachen ...

War es hilfreich?

Lösung

Für einen ersten Schuss ich keine Programmiersprache verwendet haben, nur Notepad ++

öffnete ich die XML-Datei innerhalb und kopiere und den rohen base64 Inhalt in eine neue Datei eingefügt (ohne eckige Klammern).

Danach wähle ich alles (Strg-A) und die Option Erweiterungen verwendet - Mime Tools - Base64 dekodieren. Dieser warf einen Fehler über die falsche Textlänge (muss mod 4 sein). Also habe ich nur zwei Gleichheitszeichen hinzugefügt ( ‚=‘) als Platzhalter am Ende die richtige Länge zu erhalten.

Eine weitere Wiederholung und es decodiert erfolgreich in ‚etwas‘. Speichern Sie die Datei als JPG und es öffnet sich wie ein Zauber in jedem Bildbetrachter.

Also ich würde sagen, es ist etwas falsch mit den Daten die Sie erhalten. Sie haben einfach nicht die richtigen Zahlen von Gleichheitszeichen am Ende eine Reihe von Zeichen zu füllen, die Pause in Pakete von 4 sein kann.

Der ‚easy‘ Weg wäre, das Gleichheitszeichen, bis die Dekodierung hinzuzufügen keinen Fehler werfen. Der bessere Weg, um die Anzahl der Zeichen zu zählen wäre (minus CR / LFs!) Und die benötigt diejenigen in einem Schritt hinzuzufügen.

Weitere Untersuchungen

Nachdem ich einige Codierung und das Lesen von die Funktion convert , das Problem ist ein falsche ein Gleichheitszeichen vom Hersteller angebracht wird. Notepad ++ hat kein Problem mit Tonnen von Gleichheitszeichen, aber die Funktion Convert von MS funktioniert nur mit null, eins oder zwei Zeichen. Wenn Sie also den bereits vorhandenen mit zusätzlichen Gleichheitszeichen füllen Sie einen Fehler auch! Um dieses verdammte Ding zu Arbeit zu erhalten, müssen Sie abzuschneiden alle vorhandenen Zeichen, berechnen, wie viel benötigt werden, und fügen Sie sie wieder.

Nur für die Prämie, hier ist mein Code (nicht absolut perfekt, aber genug für einen guten Startpunkt):; -)

    static void Main(string[] args)
    {
        var elements = XElement
            .Load("test.xml")
            .XPathSelectElements("//media/media-object[@encoding='base64']");
        foreach (XElement element in elements)
        {
            var image = AnotherDecode64(element.Value);
        }
    }

    static byte[] AnotherDecode64(string base64Decoded)
    {
        string temp = base64Decoded.TrimEnd('=');
        int asciiChars = temp.Length - temp.Count(c => Char.IsWhiteSpace(c));
        switch (asciiChars % 4)
        {
            case 1:
                //This would always produce an exception!!
                //Regardless what (or what not) you attach to your string!
                //Better would be some kind of throw new Exception()
                return new byte[0];
            case 0:
                asciiChars = 0;
                break;
            case 2:
                asciiChars = 2;
                break;
            case 3:
                asciiChars = 1;
                break;
        }
        temp += new String('=', asciiChars);

        return Convert.FromBase64String(temp);
    }

Andere Tipps

Die Base64-String nicht gültig ist, wie Oliver schon gesagt hat, muss der String-Länge ein Vielfaches von 4 sein, nachdem Leerzeichen entfernen. Wenn man sich dann Ende der Schnur base64 aussehen (siehe unten) sehen Sie die Linie kürzer als der Rest ist.

RRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=

Wenn Sie diese Zeile entfernen, wird Ihr Programm arbeiten, aber das resultierende Bild wird einen fehlenden Abschnitt in der unteren rechten Ecke hat. Sie müssen diese Zeile aufzufüllen, so dass die gesamte Saitenlänge corect ist. wenn Sie 3 Zeichen aus meinen Berechnungen haben es sollte funktionieren.

RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=

entfernen letzte 2 Zeichen, während Bild nicht richtig bekommen

public Image Base64ToImage(string base64String)
    {
        // Convert Base64 String to byte[]
        byte[] imageBytes=null;
        bool iscatch=true;
        while(iscatch)
        {
            try 
                {           
         imageBytes = Convert.FromBase64String(base64String);
         iscatch = false;

            }
            catch 
            {
                int length=base64String.Length;
                base64String=base64String.Substring(0,length-2);
            }
        }
        MemoryStream ms = new MemoryStream(imageBytes, 0,
          imageBytes.Length);

        // Convert byte[] to Image
        ms.Write(imageBytes, 0, imageBytes.Length);
        Image image = Image.FromStream(ms, true);
        pictureBox1.Image = image;
        return image;
    }

Versuchen Sie Linq to XML:

using System.Xml.XPath;

class Program
{
    static void Main(string[] args)
    {
        var elements = XElement
            .Load("test.xml")
            .XPathSelectElements("//media/media-object[@encoding='base64']");
        foreach (var element in elements)
        {
            byte[] image = Convert.FromBase64String(element.Value);
        }
    }
}

UPDATE:

Nachdem die XML-Datei herunterzuladen und zu analysieren, den Wert des media-object Knoten ist es klar, dass es keine gültige base64 String ist:

string value = "PUT HERE THE BASE64 STRING FROM THE XML WITHOUT THE NEW LINES";
byte[] image = Convert.FromBase64String(value);

wirft einen System.FormatException sagen, dass die Länge Basis 64 Zeichenfolge keine gültige ist. Ereignis, wenn ich die \n aus dem String entfernen es nicht funktioniert:

var elements = XElement
    .Load("20091123-125320.xml")
    .XPathSelectElements("//media/media-object[@encoding='base64']");
foreach (var element in elements)
{
    string value = element.Value.Replace("\n", "");
    byte[] image = Convert.FromBase64String(value);
}

Auch wirft System.FormatException.

Ich habe auch ein Problem mit Decodierung Base64 codierten String aus XML-Dokument (speziell OpenXML Paket Dokument).

Es stellte sich heraus, dass die String hatte zusätzliche Codierung angewandt: HTML-Codierung, so erste HTML tun Decodierung und dann Base64-Decodierung hat der Trick:

private static byte[] DecodeHtmlBase64String(string value)
{
    return System.Convert.FromBase64String(System.Net.WebUtility.HtmlDecode(value));
}

Für den Fall, jemand anderes stolpert auf dem gleichen Thema.

Nun, es ist alles sehr einfach. CDATA ist ein Knoten selbst, so dass eigentlich mediaObjectNode.InnerText <![CDATA[/9j/4AAQ[...snip...]P4Vm9zOR//Z=]]> erzeugt, die offensichtlich nicht gültig Base64-codierte Daten sind.

Um die Dinge Arbeit, die Verwendung mediaObjectNode.ChildNodes[0].Value machen und diesen Wert zu Convert.FromBase64String' passieren.

Ist codiert, das Zeichen korrekt? Die Fehler klingt wie es ein Problem gibt, die ungültige Zeichen verursacht in dem Feld erscheinen. Versuchen Sie Kopieren aus dem Text und Dekodieren von Hand, um zu sehen, ob die Daten tatsächlich gültig sind.

(Für das Protokoll, windows-1252 ist nicht genau die gleiche wie iso-8859-1, so dass die Ursache für ein Problem sein kann, abgesehen von anderen Quellen der Korruption.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top