简体   繁体   中英

Zip in memory and encode with base64

I want to zip a SVG file in memory and encode it with base64 (I want to save the zipped/base64 SVG in a XML file).

This is what I have (but I am open to everything):

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

It convert something to base64 but that is not my file since it is only a few characters long.

There are multiple problems with your code.

Most importantly, you're opening a StreamWriter to write binary data. You have:

byte[] svg;

...

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

StreamWriter is used to write text . The call you have ends up resolving to TextWriter.Write(object) . The result is as if you had called:

sw.Write(svg.ToString());

Which will output the name of the class ( "System.Byte[]" ). That's why what you're getting is 13 bytes long. It also points to another problem (see below).

So the first thing you need to do is ditch the StreamWriter and have:

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

That, at least, will write the data you want to the stream.

Now, as for reading, you have a problem. You probably can then write:

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

I don't know what your ReadToEnd method does. Perhaps it positions the stream and reads everything. But that's not going to give you what you want, which is the other problem I alluded to.

The stream returned by part.GetStream overrides the Read method and decompresses the data . So the byte array you get back will be the same as the original svg array that you wrote.

Looking at the Package API, I don't see a method that will give you the compressed data stream for a particular part.

In short, I think you need to write the entire package, convert that to base-64, and return it, as shown in Alexei's answer .

You are not seeking the stream to the beginning. Easiest fix is to use ToArray right before disposing 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());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM