how to call page which creates pdf - asp.net

I have a page called OrderExport.aspx which creates a pdf file in a folder on the server.
In my page OrderSend.aspx I have a function which sends an e-mail with the pdf file attached, like this:
Dim atc As Net.Mail.Attachment = New Attachment(stm, fileNameOrder)
mail.Attachments.Add(atc)
How can I call OrderExport.aspx from this function before sending the e-mail without showing it for the user?
I need to make sure that the pdf file exists when sending the e-mail.

You probably want to create a class rather than an aspx page to handle the PDF creation. One way to do this is to use the PDFSharp library which can handle creating the PDF document and then saving it to a stream which can be attach to an email message. You could also save the stream to a file on the server at the same time.
' Create a new PDF document
Dim document As PdfDocument = New PdfDocument
document.Info.Title = "TITLE"
Dim securitySettings As Security.PdfSecuritySettings = document.SecuritySettings
' Restrict some rights.
securitySettings.PermitAccessibilityExtractContent = False
securitySettings.PermitAnnotations = False
securitySettings.PermitAssembleDocument = False
securitySettings.PermitExtractContent = False
securitySettings.PermitFullQualityPrint = True
securitySettings.PermitModifyDocument = False
securitySettings.PermitPrint = True
' Create an empty page
Dim page As PdfPage = document.AddPage
' Get an XGraphics object for drawing
Dim gfx As XGraphics = XGraphics.FromPdfPage(page)
Dim img As XImage = XImage.FromGdiPlusImage(imgPermit)
gfx.DrawImage(img, 20, 20)
Dim stream As New MemoryStream()
document.Save(stream, False)
Dim xStream As System.IO.Stream = stream
SendEmail(sEmail, xStream)
in your mail message it would be constructed similar to this
Dim xStream As New Attachment(pdf, "FILE" + Date.Now.ToString("MM.dd.yyyy") + ".pdf")
mm.Attachments.Add(xStream)

You need to separate the GUI from the actual logic.
You presumably have code in OrderExport.aspx that creates the PDF and saves it to disk. You should put that code into a separate class, so that you can call it from OrderExport.aspx, and from the page with the "Send e-mail" button. Similarly, extract the code for sending the email from OrderSend.aspx and call it from there, and from the "Send e-mail" button.

Separation of Concerns is the best solution, but if you need a quick solution -not a good one- make the class and the function public and call it like any other class

Related

ASP.NET - How to redirect a response with a PDF to a new tab?

I have a method which I call directly from the Page_Load method, to create a PDF and print it, using PdfSharp, which is called like this:}
if(IsPostBack)
PdfSharpConvert(eventArgument, Response);
And the method looks like this:
public static void PdfSharpConvert(String html, System.Web.HttpResponse response)
{
Bitmap bitmap = new Bitmap(790, 1800);
Graphics g = Graphics.FromImage(bitmap);
XGraphics xg = XGraphics.FromGraphics(g, new XSize(bitmap.Width, bitmap.Height));
TheArtOfDev.HtmlRenderer.PdfSharp.HtmlContainer c = new TheArtOfDev.HtmlRenderer.PdfSharp.HtmlContainer();
c.SetHtml(html);
PdfDocument pdf = new PdfDocument();
PdfPage page1 = new PdfPage();
... code to paint the page ...
MemoryStream stream = new MemoryStream();
pdf.Save(stream, false);
response.Clear();
response.ContentType = "application/pdf";
response.AddHeader("content-length", stream.Length.ToString());
response.BinaryWrite(stream.ToArray());
response.Flush();
stream.Close();
response.End();
}
This works fine, I get the PDF viewer on the browser, but I'm trying to show the PDF in a different tab in the browser, not on the same one, is there a way to do this without rewriting the views I use or doing something more complicated? I tried using response.Redirect, and it does redirect, but I don't know what to give it as a parameter so it properly shows the PDF in a different page.
You require a client side javascript button.
You need to set session, or even pass the file name as part of the url.
so, say like this:
window.open('MyPdfViewer.aspsx', '_blank;);
or maybe:
window.open('MyPdfViewer.aspsx?FileName=' + MyFileName, '_blank;);
Then in the on-page load of MyPdfViewer, in the is-post back = false code stub, you place your code to pump out the pdf.
So, that 2nd new tab and web page? The on-load event of that page will have to fetch the pdf file, and push it out as you are doing now.
So pass the file name in the URL, or assume session[] has the file name to display.
You can also consider display on the current page - inside of a iFrame.

download server generated file (.vcf)

i have an interactive aspx dialog with some address data (like name, email, address,...). Now i want the user to be able by clicking a button to download the address data as vcf file.
Now, generating the vcf compatible string isn't the problem. But saving it to the client is.
While it returns the vcf string just fine, it does not open a "Save AS"-dialog. Below i attached my logic for the file download.
What am i doing wrong?
(Maybe it's worth mentioning that the code-behind function calls come from java script,...)
Thanks for any helpfull answers in advance.
Public Sub SaveText(ByVal Text As String)
Dim FileName As String = System.IO.Path.GetRandomFileName()
Using sw As New System.IO.StreamWriter(Server.MapPath(FileName + ".txt"))
sw.WriteLine(Text)
sw.Close()
End Using
Dim fs As System.IO.FileStream = Nothing
fs = System.IO.File.Open(Server.MapPath(FileName + ".txt"), System.IO.FileMode.Open)
Dim btFile(fs.Length) As Byte
fs.Read(btFile, 0, fs.Length)
fs.Close()
With HttpContext.Current.Response
.Clear()
.Buffer = True
.Expires = 0
.AddHeader("Content-disposition", "attachment;filename=" + FileName)
.AddHeader("Content-Length", btFile.Length.ToString)
.ContentType = "application/octet-stream"
.BinaryWrite(btFile)
'.OutputStream.Write(btFile, 0, btFile.Length())
.Flush()
.End()
End With
End Sub
Ok, the problem was not the above mentioned logic itself. The way i handeled the response on the client side was just wrong. The calling java script function expected something else.
I would elaborate in more detail, but this stuff here is so home grown and proprietary, it wouldn't make any sense.
Cheers.

Getting a dynamically created PDF from a URL

I have a need to aquire a pdf file generated from an aspx site.
Backstory:
I want to get schedueles from a website, I have succeded in getting the url to the scheduele, containing parameters. If you follow the url you will be shown a PDF stream, created by the site using given parameters.
http://www.novasoftware.se/ImgGen/schedulegenerator.aspx?format=pdf&schoolid=57240/sv-se&type=1&id=%7bD8920398-FA90-4960-BD47-69A8EFF7204D%7d&period=&week=38&mode=0&printer=1&colors=2&head=1&clock=1&foot=1&day=0&width=2480&height=3507&count=1&decrypt=0
This URL is what the site uses to get the appropriate scheduele and display it as a pdf.
Since it's not theoretically a PDF file, I can't download it as one using:
Dim Downloader As New WebClient
Downloader.DownloadFile(URL, fileName)
Neither can i download the content as a string using...
Dim Downloader As New WebClient
Dim Result As String = Downloader.DownloadString(URL)
...since it will result in an 500 Server Error due to missing parameters.
The only way of displaying the file/stream/document or whatever it's real name is, is to visit the given url through a browser. Given that, I tried to grab the PDF through a WebBrowser control. But since it "Can't display the XML page" (error displayed when navigating to the scheduele URL) I can't use that approach either.
So my question is, How do I download this data as a PDF or How do I get this data as a Stream that i can read with StreamReader?
Sidenotes:
The page uses no further client-side connections so I cannot backtrack it.
(I used Fiddler2 to track all the connections)
Using Fiddler, I can tell that the url SomethingSomething.com/Something.aspx generates a PDF and displays it. First few lines of the generated document (through Fiddler)
%PDF-1.4
%����
%
%wPDF by WPCubed GmbH V3.54x[0]
%
%
1 0 obj
<>
There are more information I can get from Fiddler about this site, so if you need it either try it yourself or ask me to add the information here.
Use the code below to download the file to memory stream:
Dim webRes As HttpWebResponse = Nothing
Dim memStream As New MemoryStream
Try
Dim webReq As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
webReq.Credentials = CredentialCache.DefaultCredentials
webRes = webReq.GetResponse
Dim resStream As Stream = webRes.GetResponseStream
Dim bytesRead As Integer
Do
Dim buffer(1023) As Byte
bytesRead = resStream.Read(buffer, 0, buffer.Length)
memStream.Write(buffer, 0, bytesRead)
Loop Until bytesRead = 0
Catch ex As Exception
Finally
If webRes IsNot Nothing Then
webRes.Close()
webRes = Nothing
End If
memStream.Seek(0, SeekOrigin.Begin)
End Try
' optionally save the stream into a file
memStream.WriteTo(New FileStream("d:\filename.pdf", FileMode.Create))

Print a PDF Document Programmatically

How can i Print a Pdf document through programmatically?
i am using the follwing code to print a PDF file.but when i click on print icon directly it starts printing.but i dont want it.
<asp:ImageButton ID="PrintButton" runat="server" ImageUrl="~/images/print-icon.png"
OnClick="PrintButton_Click" ToolTip="Print Document" />
My Cs Code is
protected void PrintButton_Click(object sender, EventArgs e)
{
ProcessStartInfo infoPrint = new ProcessStartInfo();
infoPrint.FileName = Session["filename"].ToString();
infoPrint.Verb = "PrintTo";
infoPrint.CreateNoWindow = true;
infoPrint.WindowStyle = ProcessWindowStyle.Normal;
infoPrint.UseShellExecute = true;
Process printProcess = new Process();
printProcess = Process.Start(infoPrint);
}
i want to open a print dialog box when the user clicks on print icon.if the user clicks on Print Button in Print dialog box then i want to start printing the document. My PDF file is in a folder on the server i want it to be printed through programmatically in asp.net.
this code will run on the server not the client. while developing the server and client are the same machine, your local workstation. Once deployed, this would execute on the server, not the user's local work station.
you can open a print dialog box using javascript
window.print();
However that will print the entire webapge, not the document specifically.
If you would like to print only the PDF, you need to stream the file to browser (not an entire webform). The user can then take advantage of the native print options within the adobe reader. There are many examples online about how to stream documents to the client's browser.
Have a look at This posst
this code add javascript line to print the pdf
Public Shared Function PrintJStoPDF(thePDF As Byte(), direct As Boolean) As Byte()
Dim BB As Byte() = Nothing
Using ms As New MemoryStream
Using reader As New PdfReader(thePDF)
Dim stamper = New PdfStamper(reader, ms)
Dim jsText As String = "var res = app.setTimeOut('this.print({bUI: true, bSilent: " & direct.ToString.ToLower & ", bShrinkToFit: false});', 200);"
stamper.JavaScript = jsText
stamper.FormFlattening = True
stamper.Writer.CloseStream = False
stamper.Close()
ms.Position = 0
BB = ms.ToArray
End Using
End Using
Return BB
End Function

FileUpload within a Wizard Control, Processed at the End

This is related to my previous question. An unforeseen issue arose with the Wizard control.
I now know how to upload to FTP, however when using the FileUpload control inside a Wizard control, when you move to the next step, the File you selected gets cleared because of the postback. I need to be able to rename the file according to the results from the Wizard before uploading. So...
I finish my wizard
It uploads some stuff to a database
Renames the file according to those results
Uploads the renamed file to the FTP server
I suspect I will need to follow a procedure something like this, having an upload button next to FileUpload
On "Upload" button click stream the file to the Web Server.
Complete the Wizard.
If the wizard completes successfully, rename file and stream to FTP server.
If the wizard fails, what? Delete the file from the web server? How?
I think I understand the process, so I would like help on how to split my FTP Upload function into two parts with the proper error handling for when the wizard fails.
It would be a great help if you please use the following code as a base. Thanks as always :)
Protected Sub UploadFile(ByVal NewFilename As String)
Dim myFtpWebRequest As FtpWebRequest
Dim myFtpWebResponse As FtpWebResponse
'Function one? - Problem, "NewFilename" depends on the output of the Wizard,
' but obviously it has not been called yet.
myFtpWebRequest = CType(WebRequest.Create(ftpServer + ftpPath + NewFilename), FtpWebRequest)
myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
myFtpWebRequest.UseBinary = True
Dim myFileStream As Stream = FileUpload1.FileContent
myFtpWebRequest.ContentLength = myFileStream.Length
'Function two?
Dim requestStream As Stream = myFtpWebRequest.GetRequestStream()
myFileStream.CopyTo(requestStream)
requestStream.Close()
myFtpWebResponse = CType(myFtpWebRequest.GetResponse(), FtpWebResponse)
myFtpWebResponse.Close()
End Sub
-- ANSWER ---
Here's my final implementation based on input from Icarus :)
For brevity I have excluded the error catching.
'This function is what kicks things off...
Protected Sub UploadFileToWebServer() Handles btnUploadFile.Click
Dim TempDir As String = "C:\TEMP", FileName As String = "uploadedfile.tmp", FilePath As String
If Not Directory.Exists(TempDir) Then
Directory.CreateDirectory(TempDir).Attributes = FileAttributes.Directory
End If
FilePath = TempDir + "\" + FileName
Session.Add("FileName", File1.FileName) 'Keep track of uploaded file name
File1.SaveAs(FilePath)
Session.Add("File", FilePath)
End Sub
After the file is uploaded to the web server, we can continue through the wizard, and when the "Finish" button is clicked, the wizard data gets submitted to the database. The filename is based on the inserted record ID. The following function gets called by the "Final" button click after the record is inserted, and the file finally gets uploaded to the FTP server with the filename changed accordingly.
Protected Sub UploadFileToFtpServer(ByVal FileLinkStr As String)
Dim myFtpWebRequest As FtpWebRequest
Dim myFtpWebResponse As FtpWebResponse
'Defines the filename, path, and upload method, and connection credentials
myFtpWebRequest = CType(WebRequest.Create(ftpServer + ftpPath + FileLinkStr), FtpWebRequest)
'Be sure to authenticate prior to uploading or nothing will upload and no error
myFtpWebRequest.Credentials = New NetworkCredential(ftpUsername, ftpPassword)
myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
myFtpWebRequest.UseBinary = True
'Streams the file to the FTP server
'Retrieves File temporarily uploaded to the Web Server during Wizard Processing
Dim iStream As New FileInfo(Session.Item("File"))
Dim myFileStream As Stream = iStream.OpenRead
myFtpWebRequest.ContentLength = myFileStream.Length
Dim requestStream As Stream = myFtpWebRequest.GetRequestStream()
myFileStream.CopyTo(requestStream)
requestStream.Close()
myFtpWebResponse = CType(myFtpWebRequest.GetResponse(), FtpWebResponse)
myFtpWebResponse.Close()
End Sub
Your understanding is correct. Once you upload the file to the web server (you'd need to place it in a temp directory somewhere and keep track of the file name you gave it) and the wizard completes successfully, you grab that file, rename it accordingly and upload it to the ftp server. If fails, simply call:
File.Delete(Path_to_file_uploaded_on_temp_directory);
You can keep track of the file name given originally, by storing it in Session, for example. When you upload the file to the server initially, do something like Session["FileName"]=Path_to_temp_directory+fileName;
On the final step of the Wizard, get the file name from Session and either rename it and upload it to the FTP Server or delete it.
Of course you need to account for possible name conflicts, etc. You can use a Guid to generate a random name for the file, for example.
I hope I explained this clearly.
EDIT
To make sure I understand correctly...
You need your user to go through all the steps of a Wizard kind of thing
During the process, you ask your user to upload a file.
Because the user has to select a file before the last step of the wizard, you are forced to upload the file immediately the user clicks on the "Next" button to go to the next step of the wizard.
At the very last step of the Wizard, you need to determine whether the file the user has selected should be uploaded to an ftp server (presumably, another box different from your web server) or should be discarded completely.
If the file needs to be uploaded to the FTP server, it needs to be renamed with a special name.
Based on the above, my suggestion is:
When the user clicks "Next" on the step where he selects the file from his computer, you need to save the file immediately to a temporary location on your web server. You save the file to this temporary folder on your web server by doing something like:
if(FileUpload1.HasFile) //user selected a file
{
try
{
//D:\temp is a temp directory on the Web Server
FileUpload1.PostedFile.SaveAs(#"D:\temp\"+FileUpload1.FileName);
//Store the FULL PATH TO the file just uploaded on Session
Session["FileName"]="D:\temp\"+FileUpload1.FileName;
}
catch (Exception ex)
{
//Handle it.
}
}
On the last step of the wizard, assuming everything was successful, do this
Dim myFtpWebRequest As FtpWebRequest
Dim myFtpWebResponse As FtpWebResponse
' You know the NewFileName because it's the output of the wizard
myFtpWebRequest = CType(WebRequest.Create(ftpServer + ftpPath + NewFilename), FtpWebRequest)
myFtpWebRequest.Method = WebRequestMethods.Ftp.UploadFile
myFtpWebRequest.UseBinary = True
'Here you need to read the Original File
Dim myFileStream As Stream = new FileStream(Session["FileName"]),FileMode.Open,FileAccess.Read,FileShare.ReadWrite)
myFtpWebRequest.ContentLength = myFileStream.Length
Dim requestStream As Stream = myFtpWebRequest.GetRequestStream()
myFileStream.CopyTo(requestStream)
requestStream.Close()
myFtpWebResponse = CType(myFtpWebRequest.GetResponse(), FtpWebResponse)
myFtpWebResponse.Close()
If you decide that you should delete the original file uploaded by the user because he did not complete the wizard successfully, you can simply do:
try
{
File.Delete (Session["FileName"]);
}
catch(Exception ex)
{
//Handle it.
}

Resources