1

I have working code in an ASP.NET Web API app that downloads an Excel spreadsheet / .xls file to the user's machine when this method is called via a click on a link:

public HttpResponseMessage Get(string unit, string begindate, string enddate)
{
    byte[] excelContents;

    string selectStmt = "SELECT BinaryData FROM ReportsGenerated WHERE FileBaseName = @fileBaseName";
    string fbn = string.Format("deliveryperformance/{0}/{1}/{2}", unit, begindate, enddate);
    using (SqlConnection connection = new SqlConnection(PlatypusWebReportsConstsAndUtils.CPSConnStr))
    using (SqlCommand cmdSelect = new SqlCommand(selectStmt, connection))
    {
        cmdSelect.Parameters.Add("@fileBaseName", SqlDbType.VarChar).Value = fbn;
        connection.Open();
        excelContents = (byte[])cmdSelect.ExecuteScalar();
        connection.Close();
    }

    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(excelContents)
    };
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = string.Format("{0}.xlsx", fbn)
    };
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return result;
}

I want to accomplish virtually the same thing from an ASP.NET MVC app with a Controller method like so:

internal static HttpResponseMessage GeneratePDFOfReportFutures()
{
    HttpResponseMessage result = null;
    futureReports = GetAllFutureReports();
    try
    {
        using (var ms = new MemoryStream())
        {
            using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
            {
                using (PdfWriter.GetInstance(doc, ms))
                {
                    doc.Open();
                    . . .
                    doc.Add(tblHeadings);

                    foreach (QueuedReports qr in futureReports)
                    {
                        . . .
                        doc.Add(tblRow);
                    }

                    var bytes = ??? // This is the conundrum

                    result = new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new ByteArrayContent(bytes)
                    };
                    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                    {
                        FileName = string.Format("{0}.pdf", "test")
                    };
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                } // memoryStream
            } // doc
        } // pdfWriter                
    } // try
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    return result;
} // GeneratePDFOfReportFutures

So in the case of the Excel file, I have already written the data to a database and then in the GET method above I read it back out, assigning the contents of that field in the table to the byte array.

In the case of the PDF file, I have no need to first store the data to a table, so I just want to cut out the DB middleman and save the contents of the byte array to a file on the user's machine. The problem is that I don't know how to assign the contents of the iTextSharp.text.Document to the byte array (see the "???" line in the GeneratePDFOfReportFutures() method).

Alternatively, how could I assign the iTextSharp.text.Document to the MemoryStream, and then assign taht to the byte array like so:

var bytes = ms.ToArray();

???

So what I need to know is, how can I assign the data from an iTextSharp.text.Document either directly to a byte array or to a MemoryStream?

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Well, you can do `ms.ToArray()`. But you need to do it outsude of `var doc` using block as it still uses it and it might not flush date from Document to stream. – Sergey Litvinov May 09 '16 at 18:42
  • But I don't think there's anything in my MemoryStream - I see no assignments to it. How can I move the data from the iTextSharp document to the MemoryStream first? – B. Clay Shannon-B. Crow Raven May 09 '16 at 18:54
  • 1
    It's not fully true. You are calling `PdfWriter.GetInstance` and passing document and memory stream there. And that method do actual linking between them. It adds created PdfWriter to document and that PdfWriter uses stream that you pass there. Yeah, it's not so clear for the first time :) – Sergey Litvinov May 09 '16 at 18:56
  • Okay, I was hoping so, but not seeing an explicit assignment gave me the fantods. – B. Clay Shannon-B. Crow Raven May 09 '16 at 18:58
  • 2
    Possible duplicate of [c# How to return a byte array from pdf using iTextsharp](http://stackoverflow.com/questions/37095802/c-sharp-how-to-return-a-byte-array-from-pdf-using-itextsharp) – mkl May 10 '16 at 06:35

0 Answers0