E
evilme
greetings and salutations, o smarter than i.
i've been working on a solution to secure the delivery of pdfs to client
browsers. we're introducing an public-website element, so i've decided to use
a webservice on the internal application webserver to pass a pdf as a byte
array to a public webserver outside the LAN, where it can be forwarded on the
response to the client browser.
i could use some advice how to improve this: i'm not entirely satisfied with
the memory useage--i'm trying to shy away from taking on making a ISAPI
extention if i can get this efficient enough as is.
more vexingly, every so often, a local user will experience an error where
the PDF is never saved/opened after they make their choice on the file
open/save dialog. further, msie's progress meter remains and looks like it's
very slowly filling (or timing out) even after the pdf has successfully been
saved/opened--is there a final signal i'm failing to send to the browser..?
I designed the web service as follows:
Public Class DocumentRequest
Inherits System.Web.Services.WebService
Private EXAMPLE_DIR As String =
Server.mappath("/ExportedPDFs/ExampleSheets/")
Private Function BinaryGetPDFDocument(ByVal FileDIR As String, ByVal
FileNum As String) As Byte()
Dim FileStreamIn As New System.IO.FileStream(FileDIR + FileNum +
".pdf", System.IO.FileMode.Open, System.IO.FileAccess.Read,
System.IO.FileShare.Read)
Dim PDFData(FileStreamIn.Length) As Byte
Dim i As Integer = FileStreamIn.Read(PDFData, 0,
CInt(FileStreamIn.Length))
While (i < CInt(FileStreamIn.Length))
System.Threading.Thread.Sleep(200)
End While
FileStreamIn.Close()
Return PDFData
End Function
Private Function CheckExistsPDFDocument(ByVal FileDIR As String, ByVal
FileNum As String) As Boolean
Try
If (System.IO.File.Exists(FileDIR + FileNum + ".pdf")) Then
Return True
Else
Return False
End If
Catch
Return False
End Try
End Function
<WebMethod()> _
Public Function GetExampleSheet(ByVal FileNum As String) As Byte()
Return BinaryGetPDFDocument(EXAMPLE_DIR, FileNum)
End Function
<WebMethod()> _
Public Function CheckExistsExampleSheet(ByVal FileNum As String) As
Boolean
Return CheckExistsPDFDocument(EXAMPLE_DIR, FileNum)
End Function
End Class
and i wrote a consume function as follows:
Friend Sub PushPDFtoClient(ByRef Response As System.Web.HttpResponse,
ByVal FileNum As String, ByVal TYPE As String)
Dim ws As New PDFRequest.DocumentRequest
Dim PDFData() As Byte
Try
If (TYPE = "EXAMPLE") Then
PDFData = ws.GetExampleSheet(FileNum)
End If
Catch ex As Exception
'EDITED - removed some private logging functions
Response.Write("<script language=""javascript""
type=""text/javascript"">alert('There was an unexpected error accessing the
PDF')</script>")
Exit Sub
End Try
Dim ms As System.IO.MemoryStream = New System.IO.MemoryStream(PDFData)
Response.Clear()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", "attachment; filename=" &
TYPE & "-" & FileNum & ".pdf; size=" & PDFData.Length.ToString)
Response.AddHeader("Content-Length", PDFData.Length.ToString)
Response.Flush()
Dim chunkSize As Integer = 1024
Dim i As Integer
For i = 0 To PDFData.Length Step chunkSize
If (Not Response.IsClientConnected) Then
Exit For
End If
Dim size As Integer = chunkSize
If (i + chunkSize >= PDFData.Length) Then
size = (PDFData.Length - i)
End If
Dim chunk(size - 1) As Byte
ms.Read(chunk, 0, size)
Response.BinaryWrite(chunk)
Response.Flush()
Next
ms.Close()
Response.End()
End Sub
i've been working on a solution to secure the delivery of pdfs to client
browsers. we're introducing an public-website element, so i've decided to use
a webservice on the internal application webserver to pass a pdf as a byte
array to a public webserver outside the LAN, where it can be forwarded on the
response to the client browser.
i could use some advice how to improve this: i'm not entirely satisfied with
the memory useage--i'm trying to shy away from taking on making a ISAPI
extention if i can get this efficient enough as is.
more vexingly, every so often, a local user will experience an error where
the PDF is never saved/opened after they make their choice on the file
open/save dialog. further, msie's progress meter remains and looks like it's
very slowly filling (or timing out) even after the pdf has successfully been
saved/opened--is there a final signal i'm failing to send to the browser..?
I designed the web service as follows:
Public Class DocumentRequest
Inherits System.Web.Services.WebService
Private EXAMPLE_DIR As String =
Server.mappath("/ExportedPDFs/ExampleSheets/")
Private Function BinaryGetPDFDocument(ByVal FileDIR As String, ByVal
FileNum As String) As Byte()
Dim FileStreamIn As New System.IO.FileStream(FileDIR + FileNum +
".pdf", System.IO.FileMode.Open, System.IO.FileAccess.Read,
System.IO.FileShare.Read)
Dim PDFData(FileStreamIn.Length) As Byte
Dim i As Integer = FileStreamIn.Read(PDFData, 0,
CInt(FileStreamIn.Length))
While (i < CInt(FileStreamIn.Length))
System.Threading.Thread.Sleep(200)
End While
FileStreamIn.Close()
Return PDFData
End Function
Private Function CheckExistsPDFDocument(ByVal FileDIR As String, ByVal
FileNum As String) As Boolean
Try
If (System.IO.File.Exists(FileDIR + FileNum + ".pdf")) Then
Return True
Else
Return False
End If
Catch
Return False
End Try
End Function
<WebMethod()> _
Public Function GetExampleSheet(ByVal FileNum As String) As Byte()
Return BinaryGetPDFDocument(EXAMPLE_DIR, FileNum)
End Function
<WebMethod()> _
Public Function CheckExistsExampleSheet(ByVal FileNum As String) As
Boolean
Return CheckExistsPDFDocument(EXAMPLE_DIR, FileNum)
End Function
End Class
and i wrote a consume function as follows:
Friend Sub PushPDFtoClient(ByRef Response As System.Web.HttpResponse,
ByVal FileNum As String, ByVal TYPE As String)
Dim ws As New PDFRequest.DocumentRequest
Dim PDFData() As Byte
Try
If (TYPE = "EXAMPLE") Then
PDFData = ws.GetExampleSheet(FileNum)
End If
Catch ex As Exception
'EDITED - removed some private logging functions
Response.Write("<script language=""javascript""
type=""text/javascript"">alert('There was an unexpected error accessing the
PDF')</script>")
Exit Sub
End Try
Dim ms As System.IO.MemoryStream = New System.IO.MemoryStream(PDFData)
Response.Clear()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", "attachment; filename=" &
TYPE & "-" & FileNum & ".pdf; size=" & PDFData.Length.ToString)
Response.AddHeader("Content-Length", PDFData.Length.ToString)
Response.Flush()
Dim chunkSize As Integer = 1024
Dim i As Integer
For i = 0 To PDFData.Length Step chunkSize
If (Not Response.IsClientConnected) Then
Exit For
End If
Dim size As Integer = chunkSize
If (i + chunkSize >= PDFData.Length) Then
size = (PDFData.Length - i)
End If
Dim chunk(size - 1) As Byte
ms.Read(chunk, 0, size)
Response.BinaryWrite(chunk)
Response.Flush()
Next
ms.Close()
Response.End()
End Sub