我收到一些带有嵌入式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不是问题。
我一直在谷歌搜索,binging,stackoverflowing和哭 - 并找不到解决方案......帮助!
添加了一个实际的示例文件(以及赏金)。请注意,可下载文件的架构有点不同,因为我在上面的示例中对其进行了简化,删除了不相关的内容......
答案 0 :(得分:9)
对于第一次拍摄我没有使用任何编程语言,只是Notepad ++
我在其中打开了xml文件,并将原始base64内容复制并粘贴到一个新文件中(没有方括号)。
之后我选择了所有内容(Strg-A)并使用了Extensions选项 - Mime Tools - Base64 decode。这引发了关于错误文本长度的错误(必须是mod 4)。所以我在末尾添加了两个等号('=')作为占位符以获得正确的长度。
另一次重试并成功解码为'某事'。只需将文件另存为.jpg,它就会像任何图片浏览器中的魅力一样打开。
所以我想说,你得到的数据有问题。他们只是在最后没有正确数量的等号来填补一些可以分成4个包的标志。
'简单'的方法是添加等号直到解码不会引发错误。更好的方法是计算字符数(减去CR / LF!)并一步添加所需的字符。
在对the convert function进行一些编码和读取之后,问题是从生产者那里错误地附加了等号。 Notepad ++没有大量等号的问题,但MS的转换功能仅适用于零,一或两个符号。因此,如果您填写已存在的附加等号,您也会收到错误!为了让这个该死的东西工作,你必须切断所有现有的标志,计算需要多少并再次添加它们。
只是为了赏金,这是我的代码(不是绝对完美的,但足以获得一个好的起点):; - )
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);
}
答案 1 :(得分:1)
如Oliver所说,base64字符串无效,删除空白字符后字符串长度必须是4的倍数。如果你看一下base64字符串的结尾(见下文),你会看到该行比其余的短。
RRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=
如果删除此行,您的程序将会正常工作,但生成的图像右下角会显示缺失的部分。您需要填充此行,以便整个字符串长度为corect。根据我的计算,如果你有3个字符,它应该可以工作。
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRX//Z=
答案 2 :(得分: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;
}
答案 3 :(得分: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
表示长度不是有效的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
。
答案 4 :(得分:0)
我还遇到了从XML文档(特别是Office OpenXML包文档)解码Base64编码字符串的问题。
事实证明,字符串应用了额外的编码:HTML编码,因此首先进行HTML解码然后进行Base64解码就可以了:
private static byte[] DecodeHtmlBase64String(string value)
{
return System.Convert.FromBase64String(System.Net.WebUtility.HtmlDecode(value));
}
以防其他人偶然发现同一问题。
答案 5 :(得分:-1)
嗯,这一切都非常简单。 CDATA
本身就是一个节点,因此mediaObjectNode.InnerText
实际上会生成<![CDATA[/9j/4AAQ[...snip...]P4Vm9zOR//Z=]]>
,这显然不是有效的Base64编码数据。
要使工作正常,请使用mediaObjectNode.ChildNodes[0].Value
并将该值传递给Convert.FromBase64String'
。
答案 6 :(得分:-2)
字符编码是否正确?该错误听起来像是一个导致无效字符出现在数组中的问题。尝试复制文本并手动解码以查看数据是否确实有效。
(对于记录,windows-1252与iso-8859-1不完全相同,因此可能是问题的原因,除非有其他腐败来源。)