itextsharp pdfsmartcopy only returning last page - asp.net

I have an issue where only the last page of my pdf is stored.
The pdf should be multiple pages long, and this works fine if I just send the pdf to the browser using Response and the mms memory stream, however I need to add it as a pdf to an email and therefore are writing mms to bytes to create a new memorystream when I create my email attachment. This is to get around the closed stream error.
This is my code
Public Shared Function SendPrePackLabels(ByVal bf_id As String, mail As String) As Boolean
Dim pars(0) As SqlParameter
pars(0) = New SqlParameter("#bf_id", SqlDbType.VarChar) With {.Value = bf_id}
Dim p As String
Dim reader As PdfReader
Dim mms As New MemoryStream
Dim rt() As Byte
Dim i As Integer = 0
Using dc As Document = New Document
Using sc As PdfSmartCopy = New PdfSmartCopy(dc, System.Web.HttpContext.Current.Response.OutputStream)
dc.Open()
With SqlHelper.ExecuteDataset(Stiletto.cnStrRMIS, CommandType.StoredProcedure, "BPM_spPrepack_Labels", pars).Tables(0)
For Each dr As DataRow In .Rows
Dim pdfr As New PdfReader("http://192.168.0.221/template.pdf")
Using ms As New MemoryStream
Using pdfs As New PdfStamper(pdfr, ms)
Dim fields As AcroFields = pdfs.AcroFields
fields.GenerateAppearances = True
fields.SetField("pono", dr.Item("po_no").ToString)
fields.SetField("ref", dr.Item("alt_code").ToString)
fields.SetField("colour", dr.Item("colour").ToString)
fields.SetField("code", dr.Item("sizerun_hdr_id").ToString)
For k As Integer = 1 To dr.Table.Columns.Count - 6
Dim j As Integer = k + 5
fields.SetField("s" & k, dr.Table.Columns(j).ColumnName.ToString)
If dr.Item(dr.Table.Columns(j).ColumnName.ToString).ToString = "" Then
p = "0"
Else
p = dr.Item(dr.Table.Columns(j).ColumnName.ToString).ToString
End If
fields.SetField("p" & k, p)
Next
fields.SetField("pack", dr.Item("sizerun_hdr_id").ToString)
Dim bcfont As BaseFont = BaseFont.CreateFont("http://192.168.0.221/ean.ttf", BaseFont.CP1252, BaseFont.EMBEDDED)
fields.SetFieldProperty("barcode", "textfont", bcfont, Nothing)
fields.SetFieldProperty("barcode", "textsize", 60.0F, Nothing)
Dim mBarcode As String = "219" & dr.Item("sizerun_hdr_id").ToString
Dim cLength As Integer = mBarcode.Length
Dim zerostoadd As Integer = 12 - cLength
Dim digit12barcode As String = mBarcode.PadRight(12, CChar("0"))
Dim FinalBarcode As String = returnCheckDigitedBarcode(digit12barcode)
fields.SetField("barcode", FinalBarcode)
Dim par(1) As SqlParameter
par(0) = New SqlParameter("#sizerun_hdr_id", SqlDbType.VarChar) With {.Value = dr.Item("sizerun_hdr_id").ToString}
par(1) = New SqlParameter("#ean13", SqlDbType.VarChar) With {.Value = FinalBarcode}
SqlHelper.ExecuteScalar(Stiletto.cnStrRMIS, CommandType.StoredProcedure, "BPM_spSizeRunEAN13", par)
pdfs.FormFlattening = True
ms.Flush()
End Using
reader = New PdfReader(ms.ToArray)
sc.AddPage(sc.GetImportedPage(reader, 1))
mms = ms
End Using
Next
End With
End Using
End Using
Dim bt() As Byte = mms.ToArray
Try
If mail.Length > 0 Then
Dim eMsg As New MailMessage()
eMsg.From = New MailAddress("myemail#mydomain.co.uk")
eMsg.To.Add(New MailAddress(mail))
Dim title As String = "<h3>Here are the Prepack Labels.</h3>"
eMsg.Subject = "Prepack Labels"
eMsg.Body = "<html>" & title & "</html>"
eMsg.IsBodyHtml = True
Dim att As Attachment = New Attachment(New MemoryStream(bt), "Prepack Labels.pdf", "application/pdf")
eMsg.Attachments.Add(att)
Dim SMTP1 As New SmtpClient
SMTP1.Host = "EX"
SMTP1.Send(eMsg)
att.Dispose()
End If
Return True
Catch ex As Exception
Return False
End Try
End Function

I'm not sure of your exact problem but I'm pretty sure your life would be easier if you broke you giant function into smaller more specific functions that do only one thing. Also, I really recommend never writing to the raw ASP.Net stream until after you've created a PDF. Instead, always write to a MemoryStream, grab the bytes and do something with them.
The code below break it into four functions. CreatePdf() loops through the database and calls CreateSinglePdf() for each row in the table, merging them with your PdfSmartCopy. SendEmail() is blissfully unaware of iTextSharp completely and just receives a raw array of bytes that is assumed to be a PDF. This is all kicked off by SendPrePackLabels() which is where you'd probably want to also Response.BinaryWrite() your bytes.
Public Shared Function SendPrePackLabels(ByVal bf_id As String, mail As String) As Boolean
Dim bt = CreatePdf(bf_id)
Return SendEmail(bt, mail)
End Function
Public Shared Function CreateSinglePdf(dr As DataRow) As Byte()
Using ms As New MemoryStream
Using pdfr As New PdfReader("http://192.168.0.221/template.pdf")
Using pdfs As New PdfStamper(pdfr, ms)
Dim fields As AcroFields = pdfs.AcroFields
fields.GenerateAppearances = True
fields.SetField("pono", dr.Item("po_no").ToString)
fields.SetField("ref", dr.Item("alt_code").ToString)
fields.SetField("colour", dr.Item("colour").ToString)
fields.SetField("code", dr.Item("sizerun_hdr_id").ToString)
Dim p As String
For k As Integer = 1 To dr.Table.Columns.Count - 6
Dim j As Integer = k + 5
fields.SetField("s" & k, dr.Table.Columns(j).ColumnName.ToString)
If dr.Item(dr.Table.Columns(j).ColumnName.ToString).ToString = "" Then
p = "0"
Else
p = dr.Item(dr.Table.Columns(j).ColumnName.ToString).ToString
End If
fields.SetField("p" & k, p)
Next
fields.SetField("pack", dr.Item("sizerun_hdr_id").ToString)
Dim bcfont As BaseFont = BaseFont.CreateFont("http://192.168.0.221/ean.ttf", BaseFont.CP1252, BaseFont.EMBEDDED)
fields.SetFieldProperty("barcode", "textfont", bcfont, Nothing)
fields.SetFieldProperty("barcode", "textsize", 60.0F, Nothing)
Dim mBarcode As String = "219" & dr.Item("sizerun_hdr_id").ToString
Dim cLength As Integer = mBarcode.Length
Dim zerostoadd As Integer = 12 - cLength
Dim digit12barcode As String = mBarcode.PadRight(12, CChar("0"))
Dim FinalBarcode As String = returnCheckDigitedBarcode(digit12barcode)
fields.SetField("barcode", FinalBarcode)
Dim par(1) As SqlParameter
par(0) = New SqlParameter("#sizerun_hdr_id", SqlDbType.VarChar) With {.Value = dr.Item("sizerun_hdr_id").ToString}
par(1) = New SqlParameter("#ean13", SqlDbType.VarChar) With {.Value = FinalBarcode}
SqlHelper.ExecuteScalar(Stiletto.cnStrRMIS, CommandType.StoredProcedure, "BPM_spSizeRunEAN13", par)
pdfs.FormFlattening = True
End Using
End Using
Return ms.ToArray()
End Using
End Function
Public Shared Function CreatePdf(ByVal bf_id As String) As Byte()
Dim pars(0) As SqlParameter
pars(0) = New SqlParameter("#bf_id", SqlDbType.VarChar) With {.Value = bf_id}
Using ms As New System.IO.MemoryStream
Using dc As Document = New Document
Using sc As PdfSmartCopy = New PdfSmartCopy(dc, ms)
dc.Open()
With SqlHelper.ExecuteDataset(Stiletto.cnStrRMIS, CommandType.StoredProcedure, "BPM_spPrepack_Labels", pars).Tables(0)
For Each dr As DataRow In .Rows
Dim pageBytes = CreateSinglePdf(dr)
Using reader = New PdfReader(pageBytes)
sc.AddPage(sc.GetImportedPage(reader, 1))
End Using
Next
End With
End Using
End Using
Return ms.ToArray()
End Using
End Function
Public Shared Function SendEmail(bt As Byte(), mail As String) As Boolean
Try
If mail.Length > 0 Then
Dim eMsg As New MailMessage()
eMsg.From = New MailAddress("myemail#mydomain.co.uk")
eMsg.To.Add(New MailAddress(mail))
Dim title As String = "<h3>Here are the Prepack Labels.</h3>"
eMsg.Subject = "Prepack Labels"
eMsg.Body = "<html>" & title & "</html>"
eMsg.IsBodyHtml = True
Dim att As Attachment = New Attachment(New MemoryStream(bt), "Prepack Labels.pdf", "application/pdf")
eMsg.Attachments.Add(att)
Dim SMTP1 As New SmtpClient
SMTP1.Host = "EX"
SMTP1.Send(eMsg)
att.Dispose()
End If
Return True
Catch ex As Exception
Return False
End Try
End Function

Related

send each PDF file in separate email automatically using VB

I'd like to ask you for some help with my problem.
I'm trying to automate sending emails with attachement separately using VB
There is a folder with few PDF files to attache to the mail
the file name start with a code of 4 digits XXXX_*
this code is the one to use to get the email from the DATABASE and every time I try to send an email it sends for all the recipient all the files
Try
Dim Smtp_Server As New SmtpClient
Dim e_mail As New Net.Mail.MailMessage()
Smtp_Server.UseDefaultCredentials = False
Smtp_Server.Credentials = New Net.NetworkCredential(TextBox3.Text, TextBox4.Text)
Smtp_Server.Port = 587
Smtp_Server.EnableSsl = True
Smtp_Server.Host = TextBox1.Text
e_mail = New Net.Mail.MailMessage()
e_mail.From = New MailAddress(TextBox3.Text)
'get users emails
Dim SQL As String = "SELECT EMail , code FROM [SagePaieSQL].[dbo].[T_SAL] WHERE EMail IS NOT NULL and MatriculeSalarie IS NOT NULL"
Dim dir As String = "C:\Users\Administrateur\Desktop\fiche_de_ paie\"
Dim output As New List(Of String)()
Dim cmd As New SqlCommand
Dim sqLdr As SqlDataReader
Dim dr As DataRow
ConnServer()
cmd.Connection = con
cmd.CommandText = SQL
Using sda As New SqlDataAdapter(cmd)
Using ds As New DataTable()
sda.Fill(ds)
sqLdr = cmd.ExecuteReader()
For i = 0 To ds.Rows.Count - 1
dr = ds.Rows(i)
Console.WriteLine(i)
e_mail.To.Add(dr("EMail").ToString())
e_mail.Subject = TextBox6.Text
e_mail.IsBodyHtml = False
e_mail.Body = (TextBox7.Text)
Dim files As String() = IO.Directory.GetFiles(dir, dr("code") & "_*")
If files.Any = False Then
MsgBox("bulltin non trouver ")
Exit Sub
Else
Button1.Enabled = False
For Each file As String In files
Dim fileName As String = IO.Path.GetFileName(file)
Dim attach As New Net.Mail.Attachment(file)
e_mail.Attachments.Add(attach)
If e_mail.Attachments.Any = True Then
MsgBox("file attached")
Smtp_Server.Send(e_mail)
MsgBox("Mail Sent")
Else
MsgBox("bulltin non attacher ")
End If
Next
End If
Next
End Using
End Using
Catch error_t As Exception
MsgBox(error_t.ToString)
End Try

Create report dynamically using ParameterFields

I have to create crystal report dynamically by using ParameterFields. - In that a single parameter have to call particular row from MySQL database dynamically. Now I called multiple values from MySql database static and single.
I need to call particular row(dynamically) from MySQL database.
Dim sql_Sel As String
Dim hIssId As Integer = 0
Dim connectionInfo1 As New ConnectionInfo()
Dim SqlCon As String = "Data source= *****"
hIssId = Request.QueryString("patID")
Try
CrystLabl.ReportSource = Nothing
Me.SqlCon.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("xyz").ConnectionString
Me.SqlCon.Open()
Dim crystalReport As New ReportDocument()
sql_Sel = "exec DI_Details #opt=1"
Dim DA As SqlDataAdapter = New SqlDataAdapter(sql_Sel, SqlCon)
Dim DG As New DataSet
DG.DataSetName = "DataSet.xsd"
DA.Fill(DG, "DataTable1")
Dim paramFields3 As New CrystalDecisions.Shared.ParameterFields()
For Each i As String In sql_Sel
Dim paramField31 As New CrystalDecisions.Shared.ParameterField()
Dim discreteVal1 As New CrystalDecisions.Shared.ParameterDiscreteValue()
discreteVal1 = New ParameterDiscreteValue()
paramField31.ParameterFieldName = "My Parameter"
discreteVal1.Value = ((DG.Tables(0).Rows(0).Item(1)) & (DG.Tables(0).Rows(0).Item(2)) & (DG.Tables(0).Rows(0).Item(3)) >(DG.Tables(0).Rows(0).Item(6)))
paramField31.CurrentValues.Add(discreteVal1)
paramFields3.Add(paramField31)
Next
CrystLabl.ParameterFieldInfo = paramFields3
CrystLabl.ReportSource = "CrystalReport.rpt"
CrystLabl.RefreshReport()
Catch ex As Exception
Finally
End Try
End Sub

ssrs to byte and byte to pdf in memory

I am trying to copy ssrs report to pdf in memory but i am getting error message when i open pdf 'file not in right format' . I am using asp.net and iTextSharp.
I want to copy ssrs to new pdf (rptpdf) file in memory and then open existing pdf and copy images to second page of that (rptpdf) pdf.
For testing purpose i am trying to see if i can copy ssrs to pdf.
Dim doc As New iTextSharp.text.Document()
Dim content As Byte()
Try
Using myMemoryStream As New MemoryStream()
Dim writer As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, myMemoryStream)
doc.Open()
Dim cb As iTextSharp.text.pdf.PdfContentByte = writer.DirectContent
Dim page As iTextSharp.text.pdf.PdfImportedPage
'--- bytes = rptViewer.ServerReport.Render("PDF", "", "", "", "", Nothing, Nothing)
Dim b() As Byte = ReportRender.GetReport()
Dim reader2 As New iTextSharp.text.pdf.PdfReader(b)
Dim pages As Integer = reader2.NumberOfPages
For i As Integer = 1 To pages
doc.SetPageSize(iTextSharp.text.PageSize.LETTER)
doc.NewPage()
page = writer.GetImportedPage(reader2, i)
cb.AddTemplate(page, 0, 0)
Next
doc.Close()
reader2.Close()
writer.Close()
content = myMemoryStream.ToArray()
myMemoryStream.Close()
End Using
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment;filename=" & "hello" & ".pdf")
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.Write(content)
UPDATED
I have managed to copy reportviewer report byte to memory stream but at add pdf file (line "writer.AddPage(page)") i get error 'object not reference '
Using myMemoryStream As New MemoryStream()
Dim rptpdfwriter As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, myMemoryStream)
If rptpdfwriter Is Nothing Then
Return
End If
doc.Open()
Dim cb As iTextSharp.text.pdf.PdfContentByte = rptpdfwriter.DirectContent
Dim page2 As iTextSharp.text.pdf.PdfImportedPage
'--- bytes = rptViewer.ServerReport.Render("PDF", "", "", "", "", Nothing, Nothing)
Dim b() As Byte = ReportRender.GetReport()
Dim reader2 As New iTextSharp.text.pdf.PdfReader(b)
Dim pages2 As Integer = reader2.NumberOfPages
For i As Integer = 1 To pages2
doc.SetPageSize(iTextSharp.text.PageSize.A4.Rotate)
doc.NewPage()
page2 = rptpdfwriter.GetImportedPage(reader2, i)
cb.AddTemplate(page2, 0, 0)
Next
reader2.Close()
For Each item As Expenses In expenses
Select Case item.Ext.ToLower
Case ".pdf"
Dim writer As New iTextSharp.text.pdf.PdfCopy(doc, myMemoryStream)
Dim reader As New iTextSharp.text.pdf.PdfReader(Server.MapPath("/docs/expenses/" + item.ExpenseID.ToString + item.Ext))
reader.ConsolidateNamedDestinations()
For i As Integer = 1 To reader.NumberOfPages
Dim page As iTextSharp.text.pdf.PdfImportedPage = writer.GetImportedPage(reader, i)
writer.AddPage(page)
Next
Dim form As iTextSharp.text.pdf.PRAcroForm = reader.AcroForm
If form IsNot Nothing Then
writer.CopyAcroForm(reader)
End If
reader.Close()
Case ".jpg"
Dim pdfWriter As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, myMemoryStream)
Dim jpg As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(Server.MapPath("/docs/expenses/" + item.ExpenseID.ToString + item.Ext))
If Not doc.IsOpen Then doc.Open()
doc.Add(jpg)
Case Else
Exit Sub
End Select
Next
doc.Close()
Content = myMemoryStream.ToArray()
myMemoryStream.Flush()
myMemoryStream.Dispose()
Response.ContentType = "application/pdf"
Response.AppendHeader("Content-Disposition", "attachment; filename=LeftCorneraaa.pdf")
Response.BinaryWrite(Content)
End Using

How to return image path to client with http handler

I use a Http Handler in my project,and i want to when client send to me a simple request ,i want read my files on server and return to client my image file url,and then client read this url and download the image.
This is example of how to retrieve image thumbnail, but you can modify its to retrieve whole picture, not thumbnail.
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim ID As String = HttpContext.Current.Request.QueryString("HotelCode")
Dim con As String = ConfigurationManager.ConnectionStrings("hotelbedsConnectionString").ConnectionString
Dim logCon As New SqlConnection(con)
Dim cmd As New SqlCommand("Select ImagePath From HOTEL_IMAGES WHERE HotelCode = #HotelCode AND Order_='1'", logCon)
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("HotelCode", SqlDbType.Int, 0).Value = ID
logCon.Open()
Dim MyData() As Byte
Dim wc = New WebClient
Dim path As String = cmd.ExecuteScalar()
If path Is Nothing Then
MyData = wc.DownloadData("http://www.blogasp.net/Images/nopic.jpg")
Else
MyData = wc.DownloadData("http://www.hotelbeds.com/giata/" & path)
End If
Dim ms As System.IO.MemoryStream = New System.IO.MemoryStream(MyData)
Dim img As System.Drawing.Image = Image.FromStream(ms)
Dim w As Integer = 100 '*** Fix Width ***'
Dim ratio As Double = img.Height / img.Width
Dim h As Integer = ratio * w
Dim thumbnail As Image = New Bitmap(w, h)
Dim graphics__2 As Graphics = Graphics.FromImage(thumbnail)
graphics__2.InterpolationMode = InterpolationMode.HighQualityBicubic
graphics__2.SmoothingMode = SmoothingMode.HighQuality
graphics__2.PixelOffsetMode = PixelOffsetMode.HighQuality
graphics__2.CompositingQuality = CompositingQuality.HighQuality
graphics__2.DrawImage(img, 0, 0, w, h)
Dim info As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
Dim encoderParameters As EncoderParameters
encoderParameters = New EncoderParameters(1)
encoderParameters.Param(0) = New EncoderParameter(Encoder.Quality, 100L)
thumbnail.Save(HttpContext.Current.Response.OutputStream, info(1), encoderParameters)
logCon.Close()
Finalize()
End Sub

(ASP.NET) SQL Data Reader returning Null Values

I am connecting to a database and then using an SQLDataReader to parse through those results and then put those results into variables that I can use at a latter time. The problem is that all of my "results.items" are returning null values. The DataReader is however, showing the proper field count when I debug.
Private Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
If e.CommandName = "editPost" Then
'Remove DataGrid'''''''''
GridView1.Visible = False
'''''''''''''''''''''''''
Dim index As Integer = Convert.ToInt32(e.CommandArgument)
Dim row As GridViewRow = GridView1.Rows(index)
Dim ID As String = GridView1.Rows(index).Cells(0).Text
''''''''''''''''''''''''''''''''''''''''CREATE Controls for Placeholder
Dim editEditor As New CuteEditor.Editor
Dim hiddenID As New HiddenField
hiddenID.ID = "hiddenID"
hiddenID.Value = ID
editEditor.ID = "editEditor"
Dim subjectTXT As New TextBox
subjectTXT.ID = "editorSubject"
Dim br As New Literal
Dim submitChanges As New Button
Dim sbjLabel As New Label
submitChanges.ID = "submitChanges"
submitChanges.Text = " Submit Changes "
submitChanges.Height = 40
submitChanges.Width = 300
sbjLabel.Text = "Subject: "
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
editEditor.AutoConfigure = CuteEditor.AutoConfigure.Simple
br.Text = "<br/><br/>"
plcEditor.Controls.Add(hiddenID)
plcEditor.Controls.Add(sbjLabel)
plcEditor.Controls.Add(subjectTXT)
subjectTXT.Width = "100"
subjectTXT.Height = "25"
subjectTXT.CssClass = "editInput"
plcEditor.Controls.Add(br)
plcEditor.Controls.Add(editEditor)
plcEditor.Controls.Add(br)
plcEditor.Controls.Add(br)
plcEditor.Controls.Add(submitChanges)
submitChanges.OnClientClick = UpdatePost()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim connStr As String = ConfigurationManager.ConnectionStrings("oakfratnewsConnectionString").ConnectionString
Dim nCon As New SqlConnection(connStr)
Dim addCon As New SqlConnection(connStr)
Dim addCom As New SqlCommand("SELECT * FROM [News] WHERE ([ID] = #ID)", addCon)
addCom.Parameters.AddWithValue("#ID", ID)
addCon.Open()
addCom.ExecuteNonQuery()
Dim results As SqlDataReader
results = addCom.ExecuteReader
While results.Read()
Dim editText As String = results.Item("Content")
Dim Subject As String = results.Item("Subject")
editEditor.Text = editText
subjectTXT.Text = Subject
End While
End If
End Sub
Where do you get the ID value?
"addCom.Parameters.AddWithValue("#ID", ID) "
Remove "addCom.ExecuteNonQuery() "
Why using
Dim editText As String = results.Item("Content")
I define before the loop the variable and then read it in this way
Dim editText As String
While results.Read()
editText = results("Content") ' without .items
...
End While

Resources