Stream PDF from a server to a web client vb.net - vb.net

We have a servlet that will deliver PDF reports to a browser. We also have a IIS server running .net apps and we want to return the PDF from the servlet as a stream to the .Net app and then the .Net app would render the PDF to the browser (we are using this technique for reason I don't need to go into here). I am not much of a VB/ Visual Studio devloper by this code works by using a web request:
Dim BUFFER_SIZE As Integer = 1024
' Create a request for the URL.
Dim serveraction As String = "https://OurSeverName/ServletContext/Dispatch?action=ajaxRunReport&reportName="
Dim request As WebRequest = _
WebRequest.Create(serveraction + ReportName.Text)
' Get the response.
Dim res As WebResponse = request.GetResponse()
' Get the stream containing content returned by the server.
Dim dataStream As Stream = res.GetResponseStream()
' Open the stream using a BinaryReader for easy access.
Dim reader As New BinaryReader(dataStream)
' Read the content.
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "inline; filename=reportfile.pdf")
Dim bytes = New Byte(BUFFER_SIZE - 1) {}
While reader.Read(bytes, 0, BUFFER_SIZE) > 0
Response.BinaryWrite(bytes)
End While
reader.Close()
' Clean up the streams and the response.
Response.Flush()
Response.Close()
The only issue is, even though the code runs quickly, it takes 20-30 seconds to render the PDF in Chrome and IE but only a few seconds in FireFox. Any idea why there is a delay in rendering the PDF? Is there a better way to stream a PDF from one server to another?

There were just a couple of very subtle tweaks that were needed (and they seem pretty insignificant and non-intuitive to me).
I added the following before setting the content type:
Response.Clear()
Response.ClearHeaders()
And I added the following after reader.Close()
Response.End()
That was it. Now the PDF files stream nicely from the Java servlet to the IIS server and to the end user's browser.

Related

VB.Net FTP read of dynamically generated file where FTPGetFileSize is not supported

I've been struggling with trying to read the configuration files on a device via FTP. The files are generated dynamically when the FTP request is sent, and the device does not support the FTPGetFileSize command.
I've lost count of the number of examples from the Web that I've tried in an attempt to solve this. Part of the problem is likely due to my inexperience with file streams. So, I'm looking for a kind soul that might be able to provide some insight.
In the code below, I'm trying two different methods. The first is a straight read of the entire file, the second attempts to control the read based whether there is anything coming in over the stream.
Both methods work on other devices that support the FTPGetFileSize command. But neither method works for this device.
Project form
Imports are:
Imports System.Net
Imports System.IO
Imports System.Text
The cmdGet_Click event code looks like this:
Dim sLocal_Path As String = "C:\Temp\FTP_Test\" + txtIPAddress.Text + "\"
System.IO.Directory.CreateDirectory(sLocal_Path)
' Complete the local path
sLocal_Path += txtFileName.Text
If System.IO.File.Exists(sLocal_Path) Then
System.IO.File.Delete(sLocal_Path) ' Make sure we don't have a collision.
End If
' Set up the Remote Path.
Dim sRemote_Path As String = "ftp://" + txtIPAddress.Text + "/gen:" + txtFileName.Text
Dim request As FtpWebRequest = CType(WebRequest.Create(sRemote_Path), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.DownloadFile
request.Credentials = New NetworkCredential(FTP_User, FTP_Password)
request.UsePassive = True
request.Timeout = 15000
request.UseBinary = False
Dim response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
Dim responseStream As Stream = response.GetResponseStream()
Dim reader As StreamReader = New StreamReader(responseStream)
Dim writeFile As StreamWriter = New StreamWriter(sLocal_Path)
If RadioReadToEnd.Checked Then
' Write the FTP stream to the target file
writeFile.Write(reader.ReadToEnd()) ' works with static files.
Else
' Write the FTP stream as long as we have data coming in.
Dim ByteCount As Integer = 0
Threading.Thread.Sleep(500)
While Not (reader.Peek() = -1)
ByteCount += 1
If ByteCount > 4095 Then ' Go up for air after every block.
ByteCount = 0 ' Reset the byte counter for the next block.
Application.DoEvents()
End If
writeFile.Write(Chr(reader.Read))
End While
End If
reader.Close()
reader.Dispose()
writeFile.Close()
writeFile.Dispose()
responseStream.Close()
responseStream.Dispose()
Note that I put a delay in just before the While Loop in the hopes that maybe something would show up in the stream to keep the loop from terminating. Apparently I need some way to prime the pump.
Edit: The DOS FTP Get works fine. My assumption is that it has some way to get around the FTPGetFileSize not being supported. Is there a way to get the WebClient FTP Methods to do the same thing with a dynamically generated file?
I need a nudge (okay, a kick) in the right direction. Any suggestions are greatly appreciated!
It is now working! The problem turned out to be a missing '/' at the root of the path.
This particular device has a drive reference in it's path that other devices my routine talks to did not have. So, between that and the error being thrown regarding the file size, I was put off of the scent.
Thanks to Martin Prikryl's comment about showing a log, I went off to create a Wireshark recording, and that's when I noticed the missing slash when I compared it to the DOS FTP Get recording. So, while I'm a little red-faced, I hope my experience helps someone else who runs into a similar problem. But mostly, I'm very relieved that I did not have to go the route of writing an FTP Client that dealt with raw commands such as POST and RETR! The WebClient tools are now working very well for this application.

Empty response HTTPWebRequest: Windows Phone 8

I am making a Windows Phone app and I am trying to get JSON data from a URL. The user needs to be logged into the website (which hosts the JSON data) in order to get JSON data and I cannot use the Web Browser control to display the data and then extract the string since the browser doesn't recognize it (for some weird reason) and asks to search for an app on Store which can handle that JSON file type. (If I open the URL in desktop browser on my Windows PC, I can see the raw JSON data). I can't use normal HTTPWebRequest or WebClient as to get JSON data the login cookies needs to be set (the JSON data is user-specific) and I can't extract the cookies from Web browser control and use it with WebClient or HTTPWebRequest. So the best thing I can do is use a special internal instance of IWebRequestCreate that is used internally by the WebBrowser. By opening background HTTP requests with that class, the cookies get automatically set as if they were created/sent by the WebBrowser control. But my code is not returning the JSON data, I get blank response, as in the string resp is empty.
Below is the code:
Dim browser = New WebBrowser()
Dim brwhttp = GetType(WebRequestCreator).GetProperty("BrowserHttp")
Dim requestFactory = TryCast(brwhttp.GetValue(Browser, Nothing), IWebRequestCreate)
Dim uri = New Uri("http://api.quora.com/api/logged_in_user?fields=inbox,notifs,following,followers")
Dim req = requestFactory.Create(uri)
req.Method = "GET"
req.BeginGetResponse(New AsyncCallback(AddressOf request_Callback), req)
Private Sub request_Callback(asyncResult As IAsyncResult)
Dim webRequest As HttpWebRequest = DirectCast(asyncResult.AsyncState, HttpWebRequest)
Dim webResponse As HttpWebResponse = DirectCast(webRequest.EndGetResponse(asyncResult), HttpWebResponse)
Dim tempStream As New MemoryStream()
webResponse.GetResponseStream().CopyTo(tempStream)
Dim sr As New StreamReader(tempStream)
Dim resp As String = sr.ReadToEnd
End Sub
What's wrong?
I found that CopyTo can leave the Stream's pointer at the end of the buffer, you probably need to reset tempStream's pointer to the beginning before attempting to read it with the StreamReader, here's the code...
webResponse.GetResponseStream().CopyTo(tempStream);
tempStream.Seek(0, SeekOrigin.Begin);
Dim sr As New StreamReader(tempStream);

FtpWebRequest.GetRequestStream hang up and fails.

I have wrote a web service, in a nutshell it uses openpop to get email messages does stuff with the content to insert into databases and saves attachments which are images. That works fine when i save images locally, it does exactley what it is suppose to. Now an added requirment was to save images to an FTP directory, so i can create my folders dynamically (they are created based upon timestamp) and that works well. My problem comes from when i try to save them to the ftp. Yes my user name and password are correct, otherwise i wouldn't be creating the directory.
Private Sub UploadFile(ByVal fileToSave As FileInfo, ByVal path As String)
Dim UploadRequest As FtpWebRequest = DirectCast(WebRequest.Create("ftp://UserName:Passowrd#999.99.999.9" & path), FtpWebRequest)
UploadRequest.Credentials = New NetworkCredential("PicService", "grean.matching18")
UploadRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
UploadRequest.UseBinary = True
UploadRequest.UsePassive = True
' Const BufferSize As Integer = 2048
' Dim content(BufferSize - 1) As Byte, dataRead As Integer
Dim bFile() As Byte = System.IO.File.ReadAllBytes(fileToSave.ToString)
'UploadRequest.ContentLength = content.Length
Using FileStream1 As FileStream = fileToSave.OpenRead()
Try
'open request to send
Using RequestStream As Stream = UploadRequest.GetRequestStream
End Using
Catch ex As Exception
Finally
'ensure file closed
FileStream1.Close()
End Try
End Using
End Sub
I have tried using Passive False and Binary False as well, i did more research on my stack trace.
And found this article but no solution as of yet. Any input would be appreciated, i am also posting another question on windows services for different issue. If you would like to take a shot at it, the other question isnt about ftp but permissions for a service on windows server 2003
This may not be the solution but I've found that the URI string has to be 'just right' and that what is 'just right' varies by the ftp server.
So ftp://server/directory/file works on some servers but needs to be ftp://server//directory/file to work on others (note the double slash after the server name)
Aso, your URI has 'password' spelled incorrectly: ftp://UserName:Passowrd#999.99.999.9 and you are supplying the credentials in a separate code line as well.

How to use HttpWebRequest to download file

Trying to download file in code.
Current code:
Dim uri As New UriBuilder
uri.UserName = "xxx"
uri.Password = "xxx"
uri.Host = "xxx"
uri.Path = "xxx.aspx?q=65"
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(uri.Uri), HttpWebRequest)
request.AllowAutoRedirect = True
request = DirectCast(WebRequest.Create(DownloadUrlIn), HttpWebRequest)
request.Timeout = 10000
'request.AllowWriteStreamBuffering = True
Dim response As HttpWebResponse = Nothing
response = DirectCast(request.GetResponse(), HttpWebResponse)
Dim s As Stream = response.GetResponseStream()
'Write to disk
Dim fs As New FileStream("c:\xxx.pdf", FileMode.Create)
Dim read As Byte() = New Byte(255) {}
Dim count As Integer = s.Read(read, 0, read.Length)
While count > 0
fs.Write(read, 0, count)
count = s.Read(read, 0, read.Length)
End While
'Close everything
fs.Close()
s.Close()
response.Close()
Running this code and checking the response.ResponseUri indicates im being redirected back to the login page and not to the pdf file.
For some reason its not authorising access what could I be missing as Im sending the user name and password in the uri? Thanks for your help
You don't need all of that code to download a file from the net
just use the WebClient class and its DownloadFile method
you should check and see if the site requires cookies (most do), i'd use a packet analyzer and run your code and see exactly what the server is returning. use fiddler or http analyzer to log packets
With UWP, this has become a more pertinent question as UWP does not have a WebClient. The correct answer to this question is if you are being re-directed to the login page, then there must be an issue with your credentials OR the setting (or lack of) header for the HttpWebRequest.
According to Microsoft, the request for downloading is sent with the call to GetResponse() on the HttpWebRequest, therefore the downloaded file SHOULD be in the stream in the response (returned by the GetResponse() call mentioned above).

Getting a PDF from WCF to WCF

Okay, here's what I have...
On one server, a WCF hosted in IIS. This one handles a bunch of stuff for an ASP.NET application which resides on the same server (mostly db calls). In the ASP app, there's an embedded iFrame which contains a PDF document viewer.
On another server, a WCF hosted in a Windows service. This one handles calls from the first WCF and kicks off a third-party document program which generates PDF files. For now, I have a dummy PDF file sitting on the C:\ drive to play with.
My mission: To somehow have a function in WCF #2 return a copy of the PDF document to WCF #1, which will save it to the local ASP application directory, so the embedded viewer can display it to a user.
So far I've tried having WCF #2 return a FileStream object but no luck there. I guess that's a big no-no in the WCF world (I'm a noob).
I have no idea how to accomplish this, most of my efforts are proving futile. How would YOU handle this? Anyone?
Thanks!
Have WCF2 take the PDF and return it as a byte array:
// fs is your FileStream
byte[] Data = new byte[fs.Length];
fs.Read(Data,0,fs.Length);
WCF1 calls WCF2 and reads the byte array, then saves it to disk
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(buff);
bw.Close();
Thanks, Jason -- I did something similar. Thought I'd post for the next guy:
WCF #2:
Public Function GetPDF_Byte() As Byte() Implements IService1.GetPDF_Byte
Dim fs As New FileStream("C:\211LD.pdf", FileMode.Open, FileAccess.Read)
Dim ImageData As Byte() = New Byte(fs.Length - 1) {}
fs.Read(ImageData, 0, System.Convert.ToInt32(fs.Length))
fs.Close()
GetPDF_Byte = ImageData
End Function
And, WCF #1 which calls #2 and writes the file to disk:
Sub Main
Dim WCF As New ServiceReference1.Service1Client
Dim ByteData As Byte()
Dim oFileStream As System.IO.FileStream
ByteData = WCF.GetPDF_Byte
oFileStream = New System.IO.FileStream("C:\NewPDF.pdf", FileMode.Create)
oFileStream.Write(ByteData, 0, ByteData.Length)
oFileStream.Close()
End Sub
Hope that can help someone else!