Reputation: 204756
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.
Upvotes: 0
Views: 4435
Reputation: 133995
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.
Upvotes: 3
Reputation: 100527
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());
}
Upvotes: 2