Image upload to Access DB in ASP.NET/VB = VOODOO WICHCRAFT REQUIRED????

N

Neo Geshel

I have examined about 80+ different upload scripts on the 'net, both in
VB and C#, and none seem to do what I need them to do. Perhaps someone
here can point me somewhere that Google hasn't reached yet (I have gone
all the way to page 50 on Google's results!!). Here are my requirements:

• I have a DataGrid. Everything will be done from here. Everything. No
exceptions. Everything will also be done in VB, without any code-behind
to confuse a beginner like me. Besides, optimization is not required,
this admin site will be used about 1-2 times a month. Scalability and
performance is NOT an issue.

• Uploading of new images will be done from the "add" line of the
datagrid, the datagrid footer in my case, and will be handled by a sub
with an e.commandname="Insert"

• The images are to be uploaded, and then several checks must be done
before they are inserted into the db.

• First Check: Does the returned stream actually contain anything? If
not, an "add" to the database cannot occur (there must be an image).

• Second Check: Is the returned stream of the filetype "image/jpeg"? If
not, the "add" to the database cannot occur (the image must be a jpeg).

• Third Check: If any dimension of the image exceeds 640 pixels, it
needs to be proportionally re-sized to a maximum size of 640 per side.
That is, an 800x600 image is to be crunched to 640x480; a 400x800 image
is to be crunched to 320x640.

• Fourth Check: If the file size of the image exceeds 150kb, it is to be
resampled downwards until the file size meets that value.

• The images are to be inserted into the database along with a comment
field populated by a <textarea /> in the datagrid.

• Since the datagrids of the Admin site is the only place that needs
thumbnails (the main site doesn't), it needs a showimage.aspx (that can
accept a table name and a unique ID from the Get string) that re-sizes
the image requested (again, proportionally) in a dynamic manner before
the images make it to the browser. All thumbnails are to have a maximum
side length of 100 pixels. This re-sizing must be done inside the
showimage.aspx

Below is the SUB that I have managed to construct so far, but it seems
to input corrupted image data into the DB. Images can't be extracted,
even with a highly simplified showimage.aspx:

Sub dgCarShowGalleryPhotos_Insert(sender As Object, e As
DataGridCommandEventArgs)
If e.CommandName = "Insert" Then
Dim imgContent as Object = e.Item.Cells(2).Controls(1)
Dim strComment as String = CType(e.Item.Cells(3).Controls(1),
Textbox).Text.Replace("'","’")
Dim imgStream As Stream = imgContent.PostedFile.InputStream()
Dim imgType as String = imgContent.PostedFile.ContentType
Dim imgLen As Int64 = imgContent.PostedFile.ContentLength
Dim imgDimension as System.Drawing.Image =
System.Drawing.Image.FromStream(imgContent.PostedFile.InputStream)
Dim imgHeight as String = imgDimension.PhysicalDimension.Height
Dim imgWidth as String = imgDimension.PhysicalDimension.Width
Dim imgbin() as Byte
If Not imgStream Is Nothing Then
If imgContent.PostedFile.ContentLength > 0 And
imgContent.PostedFile.ContentType = "image/jpeg" Then
If imgWidth > 640 Or imgHeight > 640 Then
imgbin = createThumbnail(imgStream, 640, 640)
Else
Dim imgBinaryData(imgLen) as Byte
Dim intStatus as Integer = imgStream.Read(imgBinaryData, 0, imgLen)
imgBin = imgBinaryData
End If
CType(e.Item.FindControl("add_Comment"), TextBox).Text.Replace("'","’")
Dim strSQL As String = "INSERT INTO [tblCarShowGalleryPhotos]
([CarShowGalleryYearID], [Image], [Comment]) VALUES (" &
Session("IDHolder") & ", @Image, @Comment)"
Dim objConn as New
OleDbConnection(ConfigurationSettings.AppSettings("strConn"))
objConn.Open()
Dim myCommand as OleDbCommand = new OleDbCommand(strSQL, objConn)
myCommand.CommandType = CommandType.Text
Dim parameterImage as OleDbParameter = new OleDbParameter("@Image",
OleDbType.LongVarBinary)
parameterImage.Value = imgBin
myCommand.Parameters.Add(parameterImage)
Dim parameterComment as OleDbParameter = new OleDbParameter("@Comment",
OleDbType.LongVarWChar)
parameterComment.Value = strComment
myCommand.Parameters.Add(parameterComment)
myCommand.ExecuteNonQuery()
objConn.Close()
dgCarShowGalleryPhotos.EditItemIndex = -1
BindData()
End If
End If
End If
End Sub

And here is the showimage.aspx file, which is referenced everywhere a
thumbnail is required by the datagrid:

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat=server>
Public Sub Page_Load(sender As Object, e As EventArgs)
Dim strTable as String = Request.QueryString("table")
Dim strID as String = Request.QueryString("id")
Dim myConn as New
OleDbConnection(ConfigurationSettings.AppSettings("strConn"))
Dim myCmd as New OleDbCommand("SELECT [Image] FROM " & strTable & "
WHERE [ID] = " & strID, myConn)
myConn.Open()
Dim myDataReader as OleDbDataReader =
myCmd.ExecuteReader(CommandBehavior.CloseConnection)
myDataReader.Read()
Dim imgStream(myDataReader.Item("Image")) As System.IO.MemoryStream
Dim imgStream As System.IO.MemoryStream
imgStream = myDataReader.Item("Image")
Dim imgbin as Array = createThumbnail(imgStream, 100, 100)
Response.ContentType="image/jpeg"
Response.BinaryWrite(imgbin)
myConn.Close()
End Sub
Private Function createThumbnail(ByVal ImageStream As Stream, ByVal
tWidth As Double, ByVal tHeight As Double) As Byte()
Dim g As System.Drawing.Image
=System.Drawing.Image.FromStream(ImageStream)
Dim thumbSize As New Size()
thumbSize =NewthumbSize(g.Width, g.Height, tWidth, tHeight)
Dim imgOutput As New Bitmap(g, thumbSize.Width, thumbSize.Height)
Dim imgStream As New MemoryStream()
Dim thisFormat = g.RawFormat
imgOutput.Save(imgStream, thisFormat)
Dim imgbin(imgStream.Length) As Byte
imgStream.Position = 0
Dim n As Int32 = imgStream.Read(imgbin, 0, imgbin.Length)
g.Dispose()
imgOutput.Dispose()
Return imgbin
End Function
Function NewthumbSize(ByVal currentwidth As Double, ByVal currentheight
As Double, ByVal newWidth As Double, ByVal newHeight As Double)
Dim tempMultiplier As Double
If currentheight > currentwidth Then ' portrait
tempMultiplier = newHeight / currentheight
Else
tempMultiplier = newWidth / currentwidth
End If
Dim NewSize As New Size(CInt(currentwidth * tempMultiplier),
CInt(currentheight * tempMultiplier))
Return NewSize
End Function
</script>

It also throws a number of very bad errors, particulary of the
information being of an incompatible type. "a 1-dimensional array of
byte cannot be converted to type of byte" and so forth.



Once again, I would like to say that there is NOTHING on the internet AT
ALL that is anywhere similar to what I am trying to create. If any of
you good ppl could help me find something that could fit the bill, or
correct any mistakes that I have made, I would be greatly indebted.

TIA
...Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 
C

Cor Ligthert

Neo,

As far as I can see, is everything easy to do, except the part you only name
by "upload".

Can you explain us how you have planned that.

Cor
 
C

Cor Ligthert

Little correction

* As far as I can see, is everything easy to do*, however not with a
webpage.

Cor
 
N

Neo Geshel

Cor said:
Neo,

As far as I can see, is everything easy to do, except the part you only name
by "upload".

Can you explain us how you have planned that.

Cor

What the *heck* are you talking about?? There is nothing in my code
named "upload". I only talked about the need to upload.

Or, perchance, are you talking about the second bulleted item that I was
talking about?

....Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 
K

Ken Tucker [MVP]

Hi,

Not sure why a code behind file would be confusing. You write
the code in the file much like a windows form. It just keeps people from
being able to see your code by clicking on view source. It also is quicker
because it is compiled.

Upload image file
http://support.microsoft.com/default.aspx?scid=kb;en-us;315832

Show images from database
http://msdn.microsoft.com/msdnmag/issues/04/04/CuttingEdge/

Ken
------------------
I have examined about 80+ different upload scripts on the 'net, both in
VB and C#, and none seem to do what I need them to do. Perhaps someone
here can point me somewhere that Google hasn't reached yet (I have gone
all the way to page 50 on Google's results!!). Here are my requirements:

.. I have a DataGrid. Everything will be done from here. Everything. No
exceptions. Everything will also be done in VB, without any code-behind
to confuse a beginner like me. Besides, optimization is not required,
this admin site will be used about 1-2 times a month. Scalability and
performance is NOT an issue.

.. Uploading of new images will be done from the "add" line of the
datagrid, the datagrid footer in my case, and will be handled by a sub
with an e.commandname="Insert"

.. The images are to be uploaded, and then several checks must be done
before they are inserted into the db.

.. First Check: Does the returned stream actually contain anything? If
not, an "add" to the database cannot occur (there must be an image).

.. Second Check: Is the returned stream of the filetype "image/jpeg"? If
not, the "add" to the database cannot occur (the image must be a jpeg).

.. Third Check: If any dimension of the image exceeds 640 pixels, it
needs to be proportionally re-sized to a maximum size of 640 per side.
That is, an 800x600 image is to be crunched to 640x480; a 400x800 image
is to be crunched to 320x640.

.. Fourth Check: If the file size of the image exceeds 150kb, it is to be
resampled downwards until the file size meets that value.

.. The images are to be inserted into the database along with a comment
field populated by a <textarea /> in the datagrid.

.. Since the datagrids of the Admin site is the only place that needs
thumbnails (the main site doesn't), it needs a showimage.aspx (that can
accept a table name and a unique ID from the Get string) that re-sizes
the image requested (again, proportionally) in a dynamic manner before
the images make it to the browser. All thumbnails are to have a maximum
side length of 100 pixels. This re-sizing must be done inside the
showimage.aspx

Below is the SUB that I have managed to construct so far, but it seems
to input corrupted image data into the DB. Images can't be extracted,
even with a highly simplified showimage.aspx:

Sub dgCarShowGalleryPhotos_Insert(sender As Object, e As
DataGridCommandEventArgs)
If e.CommandName = "Insert" Then
Dim imgContent as Object = e.Item.Cells(2).Controls(1)
Dim strComment as String = CType(e.Item.Cells(3).Controls(1),
Textbox).Text.Replace("'","'")
Dim imgStream As Stream = imgContent.PostedFile.InputStream()
Dim imgType as String = imgContent.PostedFile.ContentType
Dim imgLen As Int64 = imgContent.PostedFile.ContentLength
Dim imgDimension as System.Drawing.Image =
System.Drawing.Image.FromStream(imgContent.PostedFile.InputStream)
Dim imgHeight as String = imgDimension.PhysicalDimension.Height
Dim imgWidth as String = imgDimension.PhysicalDimension.Width
Dim imgbin() as Byte
If Not imgStream Is Nothing Then
If imgContent.PostedFile.ContentLength > 0 And
imgContent.PostedFile.ContentType = "image/jpeg" Then
If imgWidth > 640 Or imgHeight > 640 Then
imgbin = createThumbnail(imgStream, 640, 640)
Else
Dim imgBinaryData(imgLen) as Byte
Dim intStatus as Integer = imgStream.Read(imgBinaryData, 0, imgLen)
imgBin = imgBinaryData
End If
CType(e.Item.FindControl("add_Comment"), TextBox).Text.Replace("'","'")
Dim strSQL As String = "INSERT INTO [tblCarShowGalleryPhotos]
([CarShowGalleryYearID], [Image], [Comment]) VALUES (" &
Session("IDHolder") & ", @Image, @Comment)"
Dim objConn as New
OleDbConnection(ConfigurationSettings.AppSettings("strConn"))
objConn.Open()
Dim myCommand as OleDbCommand = new OleDbCommand(strSQL, objConn)
myCommand.CommandType = CommandType.Text
Dim parameterImage as OleDbParameter = new OleDbParameter("@Image",
OleDbType.LongVarBinary)
parameterImage.Value = imgBin
myCommand.Parameters.Add(parameterImage)
Dim parameterComment as OleDbParameter = new OleDbParameter("@Comment",
OleDbType.LongVarWChar)
parameterComment.Value = strComment
myCommand.Parameters.Add(parameterComment)
myCommand.ExecuteNonQuery()
objConn.Close()
dgCarShowGalleryPhotos.EditItemIndex = -1
BindData()
End If
End If
End If
End Sub

And here is the showimage.aspx file, which is referenced everywhere a
thumbnail is required by the datagrid:

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat=server>
Public Sub Page_Load(sender As Object, e As EventArgs)
Dim strTable as String = Request.QueryString("table")
Dim strID as String = Request.QueryString("id")
Dim myConn as New
OleDbConnection(ConfigurationSettings.AppSettings("strConn"))
Dim myCmd as New OleDbCommand("SELECT [Image] FROM " & strTable & "
WHERE [ID] = " & strID, myConn)
myConn.Open()
Dim myDataReader as OleDbDataReader =
myCmd.ExecuteReader(CommandBehavior.CloseConnection)
myDataReader.Read()
Dim imgStream(myDataReader.Item("Image")) As System.IO.MemoryStream
Dim imgStream As System.IO.MemoryStream
imgStream = myDataReader.Item("Image")
Dim imgbin as Array = createThumbnail(imgStream, 100, 100)
Response.ContentType="image/jpeg"
Response.BinaryWrite(imgbin)
myConn.Close()
End Sub
Private Function createThumbnail(ByVal ImageStream As Stream, ByVal
tWidth As Double, ByVal tHeight As Double) As Byte()
Dim g As System.Drawing.Image
=System.Drawing.Image.FromStream(ImageStream)
Dim thumbSize As New Size()
thumbSize =NewthumbSize(g.Width, g.Height, tWidth, tHeight)
Dim imgOutput As New Bitmap(g, thumbSize.Width, thumbSize.Height)
Dim imgStream As New MemoryStream()
Dim thisFormat = g.RawFormat
imgOutput.Save(imgStream, thisFormat)
Dim imgbin(imgStream.Length) As Byte
imgStream.Position = 0
Dim n As Int32 = imgStream.Read(imgbin, 0, imgbin.Length)
g.Dispose()
imgOutput.Dispose()
Return imgbin
End Function
Function NewthumbSize(ByVal currentwidth As Double, ByVal currentheight
As Double, ByVal newWidth As Double, ByVal newHeight As Double)
Dim tempMultiplier As Double
If currentheight > currentwidth Then ' portrait
tempMultiplier = newHeight / currentheight
Else
tempMultiplier = newWidth / currentwidth
End If
Dim NewSize As New Size(CInt(currentwidth * tempMultiplier),
CInt(currentheight * tempMultiplier))
Return NewSize
End Function
</script>

It also throws a number of very bad errors, particulary of the
information being of an incompatible type. "a 1-dimensional array of
byte cannot be converted to type of byte" and so forth.



Once again, I would like to say that there is NOTHING on the internet AT
ALL that is anywhere similar to what I am trying to create. If any of
you good ppl could help me find something that could fit the bill, or
correct any mistakes that I have made, I would be greatly indebted.

TIA
....Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 
N

Neo Geshel

Ken said:
Hi,

Not sure why a code behind file would be confusing. You write
the code in the file much like a windows form. It just keeps people from
being able to see your code by clicking on view source. It also is quicker
because it is compiled.

Don't need code-behind, don't need it quicker. This is for an admin site
that may get one or two visits a MONTH.

This link only talks about uploading images to the filesystem. Nothing
about databases. I need database-specific (esp. Access) information
about uploading images INTO the database. The rest I get. It's handling
the file once it's uploaded that I seem to be having a problem with.

Once again, nothing about databases, which is where I need the help.
About 90% of the information on this page had nothing to do with what I
was doing, and was in C# to boot.

Next?

....Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 
G

Guest

Neo,

You are trying to do something that is hard to do. Maybe it is time
to look at a different approach. Write a web service to interact with the
database. Use a windows forms application to interact with the web service.
 
N

Neo Geshel

It seems that Access, when it receives data in an OLE field, wraps the
data in an OLE wrapper. If the data is an image, the wrapper has to be
stripped off (the first bit, at least) before it can be displayed in a
browser.

So my big question is this: Does this solve my problem with displaying
images from an Access database? And where can I find some VB code that
can do this for my showimage.aspx file? And when I do find the code, how
much of an offset should I use? Is it the standard 78 bytes used by the
NorthWind database, or is it more or less? I also read that "Bitmap
Image.Paint.Picture" exists within the offset, so this string can be
used to determine the existence of the offset.

....Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 
K

Kevin Spencer

Hi Neo,

I'm familiar with the Access OLE Object field, and it is something to be
avoided if at all possible. In most cases, it IS at all possible. For
example, the chief purpose of a database is to store information. It is not
necessarily the chief purpose of a database to store data. quite often, a
database stores metadata, that is, information about data.

No matter how you slice it, storing binary data in a database is expensive
in terms of processor an memory usage, and it is a slow process to both
insert and extract binary data to and from a database, ESPECIALLY a
file-based database such as Access.

However, storing binary data, such as an image, is a piece of cake for the
file system, which is designed specifically for that purpose. The trick, of
course, is how to use the database, which has an excellent set of tools for
organizing and fetching data, to manage and interact with the file system.
In almost every case the solution is to store the binary data in the file
system, and to store the file name in the database.This leverages the
strengths of both, and enables the database to organize, store, and fetch
blocks of images (in a sense, which I will clarify in a bit), as well as
storing meta-data about the files, such as who uploaded them, when they were
uploaded, their size, etc., which is something the file system can't do well
at all.

So, how is this done? Well, I'm not going to write your code for you, but it
seems you can write your own, so I will tell you the process. First, you
have a means of uploading the file. This is done via an input type=file form
field, or an HtmlInputFile Control, which renders the same in the client
HTML document. You want to use a DataGrid. Fine. Use whatever container you
like, or none at all. Now, on the server side, you want to get some
information about the file, so the first thing you want to do is to create
an in-memory Bitmap from it, which you can save as any image format you
like. The in-memory Bitmap has a LockBits method, which returns a BitmapData
object. The BitmapData object can give you all the information you need
about the image.

After that, you record the image name and any other meta-data in the
database, and save the image as a file in the same format that it was
originally, which can be done using the Encoder class and the
EncoderParameters class.

As long as you store all the images in the same folder, you don't need to
store the full path in the database. In fact, this is not a good idea, as
you may want to move the physical location of the image folder in the
future. Instead, store the directory path in your web.config file, so you
can change it when necessary, and use the Path class to combine the path and
file name when storing and/or fetching image data from the database.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Ambiguity has a certain quality to it.
 
P

Paul Clement

¤ It seems that Access, when it receives data in an OLE field, wraps the
¤ data in an OLE wrapper. If the data is an image, the wrapper has to be
¤ stripped off (the first bit, at least) before it can be displayed in a
¤ browser.
¤

Actually it doesn't need to be stripped off unless you're attempting to save it to a file. You can
display it in the native application, hosted by the web browser, using Response.BinaryWrite.

However, I would highly recommend that you avoid storing the data as OLE Objects. Store them instead
in their native format (you can still use an OLE Object field).

See if the following works for you:

http://www.aspsimply.com/aspnet/ImageDBASPX.aspx


Paul
~~~~
Microsoft MVP (Visual Basic)
 
J

J. Clay

I will add my $.02 here as well. Access is NOT a good place to store
images. When you store binary data in an Access table, it tends to bloat
VERY quickly. When using Access, I always store the image as a file and
have a field in the DB for the file name. If you must store the images in
your DB, I would highly recommend looking into using SQL Server instead of
Access.

Jim
 
N

Neo Geshel

Apparently, no voodoo is required, after all. Just persistence, and
finding out the correct answers.

It turns out that my code was *nearly* correct, and for the most part
had problems in the casting of certain types. I have discovered what
those problems were, and have corrected them. I now have an
administrative interface that:

• In the Image Gallery section, will take the upload of any jpeg,and
*proportionally* resize it to a maximum dimension of 640 pixels before
stuffing it into the Access database. That is, an image at 320x200 will
be re-sized to 640x400, and an image of 640x1280 will be resized to
320x640. This is to provide a standard Gallery size for all images.

• In every datagrid that displays images that are in the database, a
showimage.aspx file pulls the images from the database, proportionally
resizes them to a maximum dimension of 100 pixels (so the datagrid can
remain compact while still showing the site owner what's been uploaded),
and displays them in the datagrid.

It turns out I didn't have to be worried about file sizes, as the
resizing of the images produces VERY acceptable file sizes (most 640x480
images weigh in at under 50Kb). As well, while many decried my use of a
database to store the images in, I had a very good reason to do so;
including filename conflict and a number of other issues that I won't
get into.

All in all, it is a very compact and efficient method of *elegantly*
inserting and updating images in a database through the use of a datagrid.

I must thank Cor Ligthert for his post here:
Which referenced this other post:
http://groups-beta.google.com/group...es.vb/msg/e06cba49dcca34dc?dmode=source&hl=en
Although he didn't give me the exact answer I needed, the webform2.aspx
code had enough "right stuff" for me to figure out the rest. I didn't
even have to use the special "Northwind" format to pull the images from
the db. Despite some things getting lost in translation between us,
thanks Cor.

If anyone wants samples of my code, please feel free to contact me
personally. Be aware of my reply-to... see my sig for more info.

...Geshel
--
**********************************************************************
My reply-to is an automatically monitored spam honeypot. Do not use it
unless you want to be blacklisted by SpamCop. Please reply to my first
name at my last name dot org.
**********************************************************************
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top