MemoryStream fails to write to other MemoryStream

428 Views Asked by At

I am having an issue when writing from one memory stream to another. I am using a NuGet package to convert PDFs to pngs. I have a need to save the images as base64 string. When I read the pdf in, it properly creates the pdf object with the correct number of expected pages. After I save the pdf to the memory stream, that stream has a length (presumably correct, but trying to create test validation now). After I send the stream to where it should be converting via copying to the other stream, the other stream never has any data. I tried the two approaches below, one more involved and one short-and-sweet based of threads I've found on here.

I cannot get my memory streams to write to one another.

This is my class

class pdf
{
    string localPath = @"C:\_Temp\MyForm.pdf";

    public pdf()
    {
        var base64String = GenerateSampleFormBase64(localPath);

        using(StreamWriter sw = new StreamWriter(@"C:\_Temp\log.txt"))
        {
            sw.WriteLine(base64String);
            sw.Flush();
        }

    }

    private static string GenerateSampleFormBase64(string path)
    {
        PdfDocument pdf = new PdfDocument(path);

        MemoryStream msPdf = new MemoryStream();
        pdf.Save(msPdf);

        var x = ConvertPdfPageToPng(msPdf);
        return Convert.ToBase64String(x);

    }

    static byte[] ConvertPdfPageToPng(MemoryStream msPng64)
    {
        // msPng64 length is 473923

        string base64;
        using(MemoryStream msPng = new MemoryStream(100))
        {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while((bytesRead = msPng64.Read(buffer, 0, buffer.Length)) > 0)
            {
                msPng.Write(buffer, 0, bytesRead);
            }

            // msPng is always length 0
            base64 = Convert.ToBase64String(msPng.GetBuffer(), 0, (int)msPng.Length);
            byte[] raw = Convert.FromBase64String(base64);

            if(raw.Length > 0)
                return raw;
            else
                throw new Exception("Failed to write to memory stream.");
        }
    }

    // This also did not work
    public static string ConvertToBase64(MemoryStream stream)
    {
        byte[] bytes;
        using(var memoryStream = new MemoryStream(100))
        {
            stream.CopyTo(memoryStream);
            bytes = memoryStream.ToArray();
        }

        return Convert.ToBase64String(bytes);
    }
}
1

There are 1 best solutions below

3
Vitaliy Shibaev On BEST ANSWER

You use PdfDocument.Save() method but it saves PDF, not PNG. You need to use PdfPage.Save instead. This sample code shows how to generate a PNG image in Base64 for the first page of a PDF document:

using (var pdf = new PdfDocument(path))
{
    PdfDrawOptions options = PdfDrawOptions.Create();
    options.BackgroundColor = new PdfRgbColor(255, 255, 255);
    options.Compression = ImageCompressionOptions.CreatePng();

    string base64 = ConvertPdfPageToBase64Png(pdf.Pages[0], options);
    File.WriteAllText("page0_base64.txt", base64);
}

private static string ConvertPdfPageToBase64Png(PdfPage page, PdfDrawOptions options)
{
    using (var stream = new MemoryStream())
    {
        page.Save(stream, options);
        return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length);
    }
}