Exceptional handling in ASP.NET file handler - asp.net

I am processing PDF/JPG/GIF files using HTTP Handler.
A popup receives a btnId in query string and detects the file extension then calls the handler with btnId and processes the request.
Files are physical stored on server with file names in DB.
When there is an issue with the file like file not found or some error I want an alert to be displayed and opened window to be closed which is not working right now.
I know the reason and that is I am writing the alert into response which will eventually land in either object tag or Image tag.
Can some one please suggest how can this be achieved. Help will be appreciated. Thanks!!!
Public Class ViewHelpContent
Inherits System.Web.UI.Page
'Method that dynamically decides based on file extension which file viewer to render
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim embed As String = String.Empty
Dim count As Integer
Dim fileName As String = String.Empty
Dim extension As String = String.Empty
Try
If Not IsPostBack Then
If Not Request.QueryString("btnId") Is Nothing Then
Dim btnId As String = Request.QueryString("btnId").ToString()
count = GetFileAttachedToButton(btnId, fileName)
extension = Path.GetExtension(fileName)
If extension.ToLower() = ".pdf" Then
embed = "<object id=""objPDFViewer"" data=""{0}{1}"" type=""application/pdf"">"
embed &= "If you are unable to view file, you can download from here"
embed &= " or there is no file available to be viewed."
embed &= "</object>"
ElseIf extension.ToLower() = ".jpeg" OrElse extension.ToLower() = ".jpg" OrElse extension.ToLower() = ".gif" Then
embed = "<img id=""objImgViewer"" src=""{0}{1}"" alt=""No file is available to be viewed."" />"
Else
ClientScript.RegisterStartupScript(Me.GetType(), "alert", "alert('No help content uploaded for this button.');", True)
Return
End If
helpContent.Text = String.Format(embed, ResolveUrl("~/ProcessHelpContent.ashx?btnId="), btnId)
End If
End If
Catch ex As Exception
ExceptionHandler.LogError(ex)
JSHelper.ShowSystemError(Me)
End Try
End Sub
End Class
Public Class ProcessHelpContent
Implements System.Web.IHttpHandler
'Sub that processes the help request and generates the requested content based on button Id
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim btnId As String = String.Empty
Dim fileName As String = String.Empty
Dim contentType As String = String.Empty
Dim outputDir As String = String.Empty
Dim count As Integer
Dim strPath As FileInfo = Nothing
Dim extension As String = String.Empty
Try
If Not context.Request.QueryString("btnId") Is Nothing Then
btnId = context.Request.QueryString("btnId").ToString()
outputDir = ConfigurationManager.AppSettings("HelpContentFilesFolder")
count = GetFileAttachedToButton(btnId, fileName)
strPath = New FileInfo(outputDir & fileName)
If Not String.IsNullOrWhiteSpace(fileName) Then
If File.Exists(strPath.FullName) Then
extension = Path.GetExtension(strPath.FullName)
If context.Request.QueryString("download") = "1" Then
context.Response.AppendHeader("Content-Disposition", Convert.ToString("attachment; filename=") & fileName)
End If
context.Response.Cache.SetCacheability(HttpCacheability.NoCache)
If extension.ToLower() = ".pdf" Then
context.Response.ContentType = "application/pdf"
ElseIf extension.ToLower() = ".jpg" OrElse extension.ToLower() = ".jpeg" Then
context.Response.ContentType = "image/jpeg"
ElseIf extension.ToLower() = ".gif" Then
context.Response.ContentType = "image/gif"
End If
context.Response.TransmitFile(strPath.FullName)
context.Response.Flush()
Else
context.Response.Write("<script>alert('Uploaded help file is missing. Please re-upload or contact administrator.'); window.close();</script>")
End If
Else
context.Response.Write("<script>alert('Uploaded help file is missing. Please re-upload or contact administrator.'); window.close();</script>")
End If
End If
Catch ex As Exception
ExceptionHandler.LogError(ex)
context.Response.Write("<script>alert('Uploaded help file is missing. Please re-upload or contact administrator.'); window.close();</script>")
End Try
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class

Related

Return ZipFile in ASHX

I have an ASHX file that receives some parameters (user and password). Using this parameters i need to send a zipfile as ASHX's result. I've written this code but when i open the downloaded zip, it appears to be corrupted.
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.Clear()
context.Response.ContentType = "application/x-zip-compressed"
Dim sLoginName As String = context.Request.QueryString("LOGIN_NAME")
Dim sLoginPassword As String = context.Request.QueryString("LOGIN_PASSWORD")
If (Not String.IsNullOrEmpty(sLoginName) And
Not String.IsNullOrEmpty(sLoginPassword)) Then
If (CheckLogin(sLoginName, sLoginPassword)) Then
Dim sZipUpdatePath As String = String.Empty
Dim sVersionToInstall As String = GetVersionToInstall(sLoginName, sLoginPassword)
Dim sZipName As String = "UPDATE.zip"
If (Not String.IsNullOrEmpty(sVersionToInstall) And
Not String.IsNullOrEmpty(sZipName)) Then
sZipUpdatePath = "~\Updates\" + sVersionToInstall + "\" + sZipName
context.Response.TransmitFile(context.Server.MapPath(sZipName))
End If
End If
End If
End Sub
How can solve it?

Asp.net vb An error occurred during local report processing in Web Service

I have a web service gift redemption.After redeeem successfull, I want to generate a invoice(pdf content) and store into database. When in debug, it prompts me "An error occurred during local report processing" when it is at the renderedBytes process.
The rdlc is in the web service folder.
The below code works in web application but not in web service.
Public dtInvDtl As New DataTable
Protected Function GenerateInvoice(ByVal sID As String) As Boolean
Dim dtInvoice As DataTable = (get record from database)
Dim dtInvoiceDtl = (get record from database)
dtInvDtl = dtInvoiceDtl
oLocalReport = New LocalReport
oLocalReport.ReportPath = HttpContext.Current.Server.MapPath("Invoice.rdlc")
Dim reportDataSource As ReportDataSource = New ReportDataSource("DS_INVOICE", dtInvoice)
oLocalReport.DataSources.Add(reportDataSource)
' Add handler for subreporting binding function
AddHandler oLocalReport.SubreportProcessing, AddressOf Subreport
Dim reportType As String = "PDF"
Dim mimeType As String = String.Empty
Dim encoding As String = String.Empty
Dim fileNameExtension As String = String.Empty
Dim deviceInfo As String = "<DeviceInfo>" & _
" <OutputFormat>PDF</OutputFormat>" & _
" <PageWidth>8.5in</PageWidth>" & _
" <PageHeight>11in</PageHeight>" & _
"</DeviceInfo>"
Dim warnings() As Warning = Nothing
Dim streams() As String = Nothing
Dim renderedBytes() As Byte
' Render the report
renderedBytes = oLocalReport.Render(reportType, deviceInfo, mimeType, encoding, fileNameExtension, streams, warnings)
End Function
'SubReporting Binding Function
Protected Sub Subreport(ByVal sender As Object, ByVal e As SubreportProcessingEventArgs)
e.DataSources.Clear()
Dim rds = New ReportDataSource("INVOICE_DTL", dtInvDtl)
e.DataSources.Add(rds)
End Sub

preview image function causing FileUpload control to reset

code snippet for my image upload:
'Read the file and convert it to Byte Array
Dim filePath As String = FileUpload1.PostedFile.FileName
Dim filename As String = Path.GetFileName(filePath)
Dim ext As String = Path.GetExtension(filename)
Dim contenttype As String = String.Empty
'Set the contenttype based on File Extension
Select Case ext
Case ".jpg"
contenttype = "image/jpg"
Exit Select
Case ".png"
contenttype = "image/png"
Exit Select
End Select
If Not contenttype Is String.Empty Then
Dim fs As Stream = FileUpload1.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
cmd.Parameters.Add("#imgName", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#contentType", SqlDbType.VarChar).Value = contenttype
cmd.Parameters.Add("#data", SqlDbType.Binary).Value = bytes
Else
cmd.Parameters.Add("#imgName", SqlDbType.VarChar).Value = DBNull.Value
cmd.Parameters.Add("#contentType", SqlDbType.VarChar).Value = DBNull.Value
cmd.Parameters.Add("#data", SqlDbType.Binary).Value = DBNull.Value
End If
con.Open()
cmd.ExecuteNonQuery()
con.Close()
preview image:
Protected Sub preview_btn_Click(sender As Object, e As EventArgs) Handles preview_btn.Click
Session("ImageBytes") = FileUpload1.FileBytes
Image1.ImageUrl = "~/Handler1.ashx"
preview_btn.BackColor = Drawing.Color.Lime
preview_btn.ForeColor = Drawing.Color.White
Image1.BorderColor = Drawing.Color.Lime
End Sub
Handler1.ashx
<%# WebHandler Language="VB" Class="Handler1" %>
Imports System
Imports System.Web
Public Class Handler1 : Implements System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
If (context.Session("ImageBytes")) IsNot Nothing Then
Dim image As Byte() = DirectCast(context.Session("ImageBytes"), Byte())
context.Response.ContentType = "image/jpeg"
context.Response.BinaryWrite(image)
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
The preview image works but whenever I invoke the preview image button, the FileUpload control get reset.
So from the FileUpload control's point of view, it is as if the user did not select any image in the first place.
I tried storing the value of FileUpload1.PostedFile.FileName in some variable first and then manually set back its value but FileUpload1.PostedFile.FileName appears to be read-only, which makes sense from a security perspective.
So workaround for this?
For a quick solution, I would do the following:
Preview - Save the posted file in session. Set the Image1 image url to handler.
Handler - Get the posted file from session. Write image to response.
Upload - Check if file exists in FileUpload1, get it. If not, get it
from session. Save image. Clear session.
Here's the code I would use:
EDIT : Changed the code to fix issue with larger (> 50kb) images
aspx.vb
Protected Sub btnUpload_Click(sender As Object, e As EventArgs) Handles btnUpload.Click
'Disabled DB operations for test
'Read the file and convert it to Byte Array
Dim filePath As String = String.Empty
Dim filename As String = String.Empty
Dim ext As String = String.Empty
Dim contenttype As String = String.Empty
Dim bytes As Byte()
If FileUpload1.HasFile Then
filePath = FileUpload1.PostedFile.FileName
Else
If (Session("MyFile") IsNot Nothing AndAlso Session("MyFileName") IsNot Nothing) Then
filePath = Session("MyFileName").ToString()
bytes = DirectCast(Session("MyFile"), Byte())
End If
End If
filename = Path.GetFileName(filePath)
ext = Path.GetExtension(filename)
'Set the contenttype based on File Extension
Select Case ext
Case ".jpg"
contenttype = "image/jpg"
Exit Select
Case ".png"
contenttype = "image/png"
Exit Select
End Select
If Not contenttype Is String.Empty Then
If FileUpload1.HasFile Then
Dim fs As Stream = FileUpload1.PostedFile.InputStream
Dim br As New BinaryReader(fs)
bytes = br.ReadBytes(fs.Length)
End If
'insert the file into database
cmd.Parameters.Add("#imgName", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#contentType", SqlDbType.VarChar).Value = contenttype
cmd.Parameters.Add("#data", SqlDbType.Binary).Value = bytes
Else
cmd.Parameters.Add("#imgName", SqlDbType.VarChar).Value = DBNull.Value
cmd.Parameters.Add("#contentType", SqlDbType.VarChar).Value = DBNull.Value
cmd.Parameters.Add("#data", SqlDbType.Binary).Value = DBNull.Value
End If
con.Open()
cmd.ExecuteNonQuery()
con.Close()
'Cleanup
Session("MyFile") = Nothing
Session("MyFileName") = Nothing
End Sub
Protected Sub preview_btn_Click(sender As Object, e As EventArgs) Handles preview_btn.Click
If FileUpload1.PostedFile IsNot Nothing Then
Dim file As HttpPostedFile = FileUpload1.PostedFile
Dim data As Byte() = New [Byte](file.ContentLength - 1) {}
file.InputStream.Read(data, 0, file.ContentLength)
Session("MyFile") = data
Session("MyFileName") = FileUpload1.PostedFile.FileName
Image1.ImageUrl = "~/Handler1.ashx"
preview_btn.BackColor = Drawing.Color.Lime
preview_btn.ForeColor = Drawing.Color.White
Image1.BorderColor = Drawing.Color.Lime
End If
End Sub
Handler1.ashx
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
If (context.Session("MyFile")) IsNot Nothing Then
Dim storedImage = TryCast(context.Session("MyFile"), Byte())
If storedImage IsNot Nothing Then
context.Response.ContentType = "image/jpeg"
context.Response.BinaryWrite(storedImage)
End If
End If
End Sub
Hope it helps!

How to detect password protected word, excel file?

My application will search ms office document such as word, excel, etc in folder and then read the tag in metadata.
But my function will hang/stop when the function try to open a password protected (need password) file.
How can I detect the file had been password protected? If yes, I skip this file and proceed on next file.
'Read Word metadata
Public Sub ReadWord(WordFileName As String)
Dim Wapp As New Microsoft.Office.Interop.Word.Application
Dim docWord As New Microsoft.Office.Interop.Word.Document
If Wapp Is Nothing Then
Wapp = New Microsoft.Office.Interop.Word.Application
End If
If docWord Is Nothing Then
docWord = New Microsoft.Office.Interop.Word.Document
Else
docWord.Close()
End If
docWord = Wapp.Documents.Open(WordFileName)
Dim _BuiltInProperties As Object = docWord.BuiltInDocumentProperties
If Not _BuiltInProperties Is Nothing Then
word_keyword = _BuiltInProperties("Keywords").Value
End If
If Not docWord Is Nothing Then
docWord.Close()
End If
If Not Wapp Is Nothing Then
Wapp.Quit()
End If
End Sub
'Read Excel metadata
Public Sub ReadExcel(ExcelFileName As String)
Dim Wapp As New Microsoft.Office.Interop.Excel.Application
Dim excelbook As Microsoft.Office.Interop.Excel.Workbook
If Wapp Is Nothing Then
Wapp = New Microsoft.Office.Interop.Excel.Application
End If
excelbook = Wapp.Workbooks.Open(ExcelFileName)
Dim _BuiltInProperties As Object = excelbook.BuiltinDocumentProperties
If Not _BuiltInProperties Is Nothing Then
excel_keyword = _BuiltInProperties("Keywords").Value
End If
If Not excelbook Is Nothing Then
excelbook.Close()
End If
If Not Wapp Is Nothing Then
Wapp.Quit()
End If
End Sub

Access sessions in asp.net handler

I am trying to upload images using generic handler as shown below and I have a normal aspx page where I am showing all the uploaded images after uploading.Everything is working fine.
<%# WebHandler Language="VB" Class="Upload"%>
Imports System
Imports System.Web
Imports System.Threading
Imports System.Web.Script.Serialization
Imports System.IO
Public Class Upload : Implements IHttpHandler, System.Web.SessionState.IRequiresSessionState
Public Class FilesStatus
Public Property thumbnail_url() As String
Public Property name() As String
Public Property url() As String
Public Property size() As Integer
Public Property type() As String
Public Property delete_url() As String
Public Property delete_type() As String
Public Property [error]() As String
Public Property progress() As String
End Class
Private ReadOnly js As New JavaScriptSerializer()
Private ingestPath As String
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim r = context.Response
ingestPath = context.Server.MapPath("~/UploadedImages/")
r.AddHeader("Pragma", "no-cache")
r.AddHeader("Cache-Control", "private, no-cache")
HandleMethod(context)
End Sub
Private Sub HandleMethod(ByVal context As HttpContext)
Select Case context.Request.HttpMethod
Case "HEAD", "GET"
ServeFile(context)
Case "POST"
UploadFile(context)
Case "DELETE"
DeleteFile(context)
Case Else
context.Response.ClearHeaders()
context.Response.StatusCode = 405
End Select
End Sub
Private Sub DeleteFile(ByVal context As HttpContext)
Dim filePath = ingestPath & context.Request("f")
If File.Exists(filePath) Then
File.Delete(filePath)
End If
End Sub
Private Sub ServeFile(ByVal context As HttpContext)
If String.IsNullOrEmpty(context.Request("f")) Then
ListCurrentFiles(context)
Else
DeliverFile(context)
End If
End Sub
Private Sub UploadFile(ByVal context As HttpContext)
Dim statuses = New List(Of FilesStatus)()
Dim headers = context.Request.Headers
If String.IsNullOrEmpty(headers("X-File-Name")) Then
UploadWholeFile(context, statuses)
Else
UploadPartialFile(headers("X-File-Name"), context, statuses)
End If
WriteJsonIframeSafe(context, statuses)
End Sub
Private Sub UploadPartialFile(ByVal fileName As String, ByVal context As HttpContext, ByVal statuses As List(Of FilesStatus))
If context.Request.Files.Count <> 1 Then
Throw New HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request")
End If
Dim inputStream = context.Request.Files(0).InputStream
Dim fullName = ingestPath & Path.GetFileName(fileName)
Using fs = New FileStream(fullName, FileMode.Append, FileAccess.Write)
Dim buffer = New Byte(1023) {}
Dim l = inputStream.Read(buffer, 0, 1024)
Do While l > 0
fs.Write(buffer, 0, l)
l = inputStream.Read(buffer, 0, 1024)
Loop
fs.Flush()
fs.Close()
End Using
statuses.Add(New FilesStatus With {.thumbnail_url = "Thumbnail.ashx?f=" & fileName, .url = "Upload.ashx?f=" & fileName, .name = fileName, .size = CInt((New FileInfo(fullName)).Length), .type = "image/png", .delete_url = "Upload.ashx?f=" & fileName, .delete_type = "DELETE", .progress = "1.0"})
End Sub
Private Sub UploadWholeFile(ByVal context As HttpContext, ByVal statuses As List(Of FilesStatus))
For i As Integer = 0 To context.Request.Files.Count - 1
Dim file = context.Request.Files(i)
file.SaveAs(ingestPath & Path.GetFileName(file.FileName))
Thread.Sleep(1000)
Dim fname = Path.GetFileName(file.FileName)
statuses.Add(New FilesStatus With {.thumbnail_url = "Thumbnail.ashx?f=" & fname, .url = "Upload.ashx?f=" & fname, .name = fname, .size = file.ContentLength, .type = "image/png", .delete_url = "Upload.ashx?f=" & fname, .delete_type = "DELETE", .progress = "1.0"})
Next i
End Sub
Private Sub WriteJsonIframeSafe(ByVal context As HttpContext, ByVal statuses As List(Of FilesStatus))
context.Response.AddHeader("Vary", "Accept")
Try
If context.Request("HTTP_ACCEPT").Contains("application/json") Then
context.Response.ContentType = "application/json"
Else
context.Response.ContentType = "text/plain"
End If
Catch
context.Response.ContentType = "text/plain"
End Try
Dim jsonObj = js.Serialize(statuses.ToArray())
context.Response.Write(jsonObj)
End Sub
Private Sub DeliverFile(ByVal context As HttpContext)
Dim filePath = ingestPath & context.Request("f")
If File.Exists(filePath) Then
context.Response.ContentType = "application/octet-stream"
context.Response.WriteFile(filePath)
context.Response.AddHeader("Content-Disposition", "attachment, filename=""" & context.Request("f") & """")
Else
context.Response.StatusCode = 404
End If
End Sub
Private Sub ListCurrentFiles(ByVal context As HttpContext)
Dim files = New List(Of FilesStatus)()
Dim names = Directory.GetFiles(context.Server.MapPath("~/UploadedImages/"), "*", SearchOption.TopDirectoryOnly)
For Each name In names
Dim f = New FileInfo(name)
files.Add(New FilesStatus With {.thumbnail_url = "Thumbnail.ashx?f=" & f.Name, .url = "Upload.ashx?f=" & f.Name, .name = f.Name, .size = CInt(f.Length), .type = "image/png", .delete_url = "Upload.ashx?f=" & f.Name, .delete_type = "DELETE"})
Next name
context.Response.AddHeader("Content-Disposition", "inline, filename=""files.json""")
Dim jsonObj = js.Serialize(files.ToArray())
context.Response.Write(jsonObj)
context.Response.ContentType = "application/json"
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Now I want to add a session variable by generating a random string and add the uploaded images to the newly created random string.
1.I have seen this Question on SO to use System.Web.SessionState.IRequiresSessionState for sessions and how do I create a folder with that and add my images to that folder after doing that how do I access this session variable in my normal aspx page.
2.(Or) the better way is create session variable in aspx page and pass that to handler?If so how can I do that?
3 .I am trying to find the control from my handler.Is that possible?If anyone knows how to get this then also my problem will get resolved so that I am trying to create a session from m aspx page.
Can anyone explain the better way of handling this situation.
I completely agree with jbl's comment.
You can get and set session using HttpContext.Current.Session anywhere on your project.
No matter where you create the session. Just make sure that the session exists before you access it.
Not sure what exactly you are asking here(need some more explanation).
Here is an example, where I used session on HttpHandler. However, it is on c#(hope you can understand).
This is not really an answer but #Knvn wrote a C# example which I couldn't understand so I used a converter to convert it to VB. Posted it here in case it helps someone in the future.
Public Class HttpHandler
Implements IHttpHandler
Implements IRequiresSessionState
Public Sub New()
End Sub
Public Sub ProcessRequest(context As HttpContext)
Dim Request As HttpRequest = context.Request
Dim Response As HttpResponse = context.Response
If SessionHandler.Current.UserID = 0 Then
Response.Redirect("~/Default.aspx")
Else
Try
If Request.Path.EndsWith(".pdf") Then
Dim client As New WebClient()
Dim buffer As [Byte]() = client.DownloadData(HttpContext.Current.Server.MapPath(Request.Path))
Response.ContentType = "application/pdf"
Response.AddHeader("content-length", buffer.Length.ToString())
Response.BinaryWrite(buffer)
Else
Using reader As New StreamReader(HttpContext.Current.Server.MapPath(Request.Path))
Response.Write(reader.ReadToEnd())
End Using
End If
Catch
Response.Redirect("~/Default.aspx")
End Try
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean
' To enable pooling, return true here.
' This keeps the handler in memory.
Get
Return False
End Get
End Property
End Class

Resources