Search code examples
asp.netvb.netimagefile-uploadpreview

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?


Solution

  • For a quick solution, I would do the following:

    1. Preview - Save the posted file in session. Set the Image1 image url to handler.
    2. Handler - Get the posted file from session. Write image to response.
    3. 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!