5

base64 でエンコードされた画像が埋め込まれた xml ファイルを受け取りました。これをデコードしてファイルとして保存する必要があります。

このようなファイルの変更されていない (圧縮されていない) 例は、以下からダウンロードできます。

20091123-125320.zip (60KB)

ただし、「Base-64 char 配列の長さが無効です」や「Base-64 文字列の文字が無効です」などのエラーが発生します。コードでエラーが発生したコードの行をマークしました。

ファイルは次のようになります。

<?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>

そして、このように処理するコード:

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
        }

xml-data は企業の新聞システムからのものなので、ファイルに問題はないと確信しています。ファイルを処理する方法に何か問題があるに違いありません。それは単に間違っています。エンコーディングの問題かも?

mediaObjectNode.InnerText の内容を書き出そうとしましたが、これは base64 でエンコードされたデータであるため、xml-doc のナビゲートは問題ではありません。

私はグーグル、ビンジング、スタックオーバーフロー、泣き叫びを繰り返してきましたが、解決策が見つかりませんでした...助けてください!

編集:

実際のサンプル ファイル (および報奨金) を追加しました。上記の例では単純化して無関係なものを削除しているため、ダウンロード可能なファイルのスキーマは少し異なることに注意してください...

4

7 に答える 7

9

最初のショットでは、プログラミング言語は使用せず、メモ帳 ++ のみを使用しました

内部でxmlファイルを開き、未加工のbase64コンテンツをコピーして新しいファイルに貼り付けました(角括弧なし)。

その後、すべて (Strg-A) を選択し、拡張機能 - Mime ツール - Base64 デコード オプションを使用しました。これにより、テキストの長さが間違っているというエラーがスローされました (mod 4 である必要があります)。したがって、正しい長さを取得するために、最後にプレースホルダーとして 2 つの等号 ('=') を追加しました。

もう一度再試行すると、「何か」に正常にデコードされました。ファイルを .jpg として保存するだけで、どの画像ビューアーでも魅力的に開きます。

つまり、取得するデータに何か問題があると言えます。それらは、4つのパケットに分割できる記号の数まで埋めるために、最後に適切な数の等号を持っていません.

「簡単な」方法は、デコードでエラーが発生しなくなるまで等号を追加することです。より良い方法は、文字数 (マイナス CR/LF!) を数え、必要な文字を 1 ステップで追加することです。

さらなる調査

convert functionのコーディングと読み取りの後、問題はプロデューサーからの等号の間違った添付です。Notepad++ は大量の等号に問題はありませんが、MS の Convert 関数は 0、1、または 2 つの記号でしか機能しません。したがって、既存のものを追加の等号で埋めると、エラーも発生します! このいまいましいことを機能させるには、既存の兆候をすべて切り取り、必要な量を計算して、再度追加する必要があります。

賞金のために、これが私のコードです(完全に完璧ではありませんが、良い出発点としては十分です): ;-)

    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);
    }
于 2009-11-23T13:04:10.397 に答える
1

オリバーがすでに述べたように、base64文字列は無効です。空白文字を削除した後、文字列の長さは4の倍数でなければなりません。base64文字列の終わり(以下を参照)を見ると、行が残りの行よりも短いことがわかります。

RRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=

この行を削除すると、プログラムは機能しますが、結果の画像の右下隅にセクションがありません。文字列全体の長さが正しくなるように、この行を埋める必要があります。私の計算によると、3文字あれば、うまくいくはずです。

RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=
于 2009-11-23T16:17:37.467 に答える
1

画像が適切に取得されない間に最後の2文字を削除する

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;
    }
于 2013-10-21T12:31:10.170 に答える
0

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

アップデート:

XML ファイルをダウンロードしてmedia-objectノードの値を分析すると、有効な base64 文字列ではないことが明らかになります。

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

System.FormatException長さが有効な base 64 文字列ではないということわざをスローします。文字列からを削除したときのイベント\nは機能しません:

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

も投げSystem.FormatExceptionます。

于 2009-11-20T15:38:07.813 に答える
0

また、XML ドキュメント (具体的には Office OpenXML パッケージ ドキュメント) から Base64 でエンコードされた文字列をデコードする際にも問題が発生しました。

文字列には追加のエンコーディングが適用されていることが判明しました: HTML エンコーディングなので、最初に HTML デコードを行い、次に Base64 デコードを行うとうまくいきました:

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

他の誰かが同じ問題に遭遇した場合に備えて。

于 2013-12-06T13:46:42.977 に答える
-1

まあ、それはすべて非常に簡単です。CDATAはノード自体であるため、mediaObjectNode.InnerText実際には を生成しますが<![CDATA[/9j/4AAQ[...snip...]P4Vm9zOR//Z=]]>、これは明らかに有効な Base64 エンコード データではありません。

物事を機能させるにはmediaObjectNode.ChildNodes[0].Value、その値を使用してに渡しますConvert.FromBase64String'

于 2009-11-20T15:36:20.693 に答える
-2

文字コードは正しいですか?エラーは、無効な文字が配列に表示される問題があるようです。テキストをコピーして手動でデコードし、データが実際に有効かどうかを確認してください。

(記録として、windows-1252 は iso-8859-1 と完全に同じではないため、他の破損の原因を除いて、それが問題の原因である可能性があります。)

于 2009-11-20T15:35:54.783 に答える