Delphi 2010 - 解码来自XML doc的Base64编码图像

时间:2010-04-15 11:19:47

标签: delphi xml-serialization delphi-2010 base64

我正在尝试从我的应用程序中的XML文档解码base64编码的EMF图像并在屏幕上呈现它,但是,它似乎永远不会出现。

如果我将XML文档中的数据复制/粘贴到Notepad ++中并使用Base64 Decode选项并将文件另存为.emf,则可以在mspaint中打开。所以我认为问题是我如何解码它。

我尝试了以下这些文章中描述的解码方法:

How to encode / decode Base 64 string
http://www.swissdelphicenter.ch/torry/showcode.php?id=1223

我也试过TIdDecoderMIME课无济于事。

有没有人知道从XML解码base64编码字符串的最可靠方法?

实施例

procedure TXmlSerializer.SaveImageFromString(const AValue: string);
var
  StrStream: TStringStream;
  Decoder: TIdDecoderMIME;
begin
  // AValue is base64 encoded string from XML doc
  Decoder := TIdDecoderMIME.Create(nil);
  try
    StrStream := TStringStream.Create(Decoder.DecodeString(AValue));
    try
      StrStream.SaveToFile('MyPath\Image.emf');
    finally
      StrStream.Free;
    end;
  finally
    Decoder.Free;
  end;
end;

为什么以上不起作用,而是将原始数据复制到Notepad ++和解码&保存为.emf有效吗?

3 个答案:

答案 0 :(得分:7)

您正在使用字符串存储二进制数据; Delphi 2010的unicode-ness可能会在这里“责怪”。

尝试使用支持解码到流的base64解码器,并直接解码为TFileStream;我使用JclMime(Jedi的JCL的一部分),但是如果没有Indy MIME方法可以在流而不是字符串上工作,我会感到惊讶。

由于JclMime仅支持流到流的解码,因此在从XML有效负载解码base64数据时使用以下包装器:

procedure MimeDecode(const inputString: string; const outputStream: Tstream);
var
  ss: TStringStream;
begin
  ss := TStringStream.Create(inputString);
  try
    JclMime.MimeDecodeStream(ss, outputStream);
  finally
    ss.free;
  end;
end;

答案 1 :(得分:2)

TIdDecoderMIME工作得很好。试过并测试过。只需查看Indy提供的代码示例。

此外,OmniXML具有OmniXMLUtils.pas单元,其中包含各种用于XML的实用程序功能。 在里面你可以找到独立的Base64编码/解码功能。您可以复制粘贴它们或按原样使用它们。

否则使用TIdDecoderMIME发布代码。你的代码一定是个错误。

编辑:

您必须注意您将字符串写为单字节顺序流。 Base64适用于字节(ASCII字符),如果为它提供2字节的unicode字符串,它将无法正常工作。如果您将Base64编码的序列作为字符串并将其写入流,则会出现错误,因为此类流的长度将是原始流的两倍。

您可以使用TStringStream或使用AnsiStrings执行任务。只要您坚持这一点,编码/解码就能正常工作。

您也可以使用我的SimpleStorage为您完成所有工作。从XML读取图像可以完成如下简单的任务:

  Jpeg := TJPEGImage.Create;
  try
    Jpeg.LoadFromStream(SrcStorage.Get('Image').Filter('gzip').AsBinary.Stream);
  finally
    Jpeg.Free;
  end;

容易不是它(并且它在此过程中也被解压缩)。 :)

答案 2 :(得分:0)

确保您只解码属性值而不是整个XML。

在您的代码中,请确保在读取之前将流的位置设置为0.

StrStream.Seek(0, soFromBeginning);

我不熟悉TStringStream的SaveToFile()方法。你确定吗?

此外,由于Delphi 2010支持unicode字符串,因此在处理二进制数据时可能需要使用AnsiStrings。将多字节字符类型与单字节数据混合时要小心。