0

我想在内存中压缩一个 SVG 文件并使用 base64 对其进行编码(我想将压缩/base64 SVG 保存在 XML 文件中)。

这就是我所拥有的(但我对一切都持开放态度):

byte[] svg = File.ReadAllBytes("test.SVG");
using (MemoryStream ms = new MemoryStream())
{  
    using (Package pkg = Package.Open(ms, FileMode.Create)) 
    {
        PackagePart part = pkg.CreatePart(new Uri("/test.SVG", UriKind.Relative), "image/svg+xml", CompressionOption.Normal);  
        using (Stream strm = part.GetStream()) 
        {  
            using (StreamWriter sw = new StreamWriter(strm)) 
            {  
                sw.Write(svg);
            }

            byte[] b = ReadToEnd(part.GetStream());
            return Convert.ToBase64String(b);
        }
    }
}

它将某些内容转换为base64,但这不是我的文件,因为它只有几个字符长。

4

2 回答 2

3

您的代码存在多个问题。

最重要的是,您正在打开一个StreamWriter来写入二进制数据。你有:

byte[] svg;

...

using (StreamWriter sw = new StreamWriter(...))
{
    sw.Write(svg);
}

StreamWriter是用来写文字的。您的电话最终解决为TextWriter.Write(object). 结果就像您调用了:

sw.Write(svg.ToString());

它将输出类的名称 ( "System.Byte[]")。这就是为什么你得到的是 13 个字节长的原因。它还指出了另一个问题(见下文)。

因此,您需要做的第一件事就是放弃StreamWriter并拥有:

    using (Stream strm = part.GetStream()) 
    {  
        strm.Write(svg, 0, svg.Length)
    }

至少,这会将您想要的数据写入流。

现在,至于阅读,你有一个问题。然后你可能可以写:

        strm.Flush();
        strm.Position = 0;
        byte[] b = ReadToEnd(part.GetStream());
        return Convert.ToBase64String(b);

我不知道你的ReadToEnd方法是做什么的。也许它定位流并读取所有内容。但这不会给你你想要的,这是我提到的另一个问题。

由返回的流part.GetStream覆盖该Read方法并解压缩数据。因此,您返回的字节数组将与svg您编写的原始数组相同。

查看 Package API,我没有看到可以为您提供特定部分的压缩数据流的方法。

简而言之,我认为您需要编写整个包,将转换为 base-64,然后返回,如Alexei's answer所示。

于 2013-09-26T21:00:17.397 回答
2

你不是从一开始就寻找流。最简单的解决方法是ToArray在处理之前使用MemoryStream

using (MemoryStream ms = new MemoryStream())
{
  // Whatever manipulations with stream you need goes here.
  ...
  ms.Close(); // guarantees to commit all changes, 
              // safe to do as `ToArray` work on disposed stream
  return Convert.ToBase64String(ms.ToArrray());
}
于 2013-09-26T20:01:47.247 回答