Click here to Skip to main content
Click here to Skip to main content

Add .NET thumbnailing to a classic ASP Multi-upload image gallery

By , 19 Jul 2010
 

Introduction

In my original article, I explained the methodology for creating an asynchronous upload mechanism for images, along with a full featured image gallery manager that displayed the galleries using SimpleViewer, a flexible freeware Flash image gallery. While functional, the original solution had a serious limitation for widespread use: it relied on on a DLL for image manipulation. This precludes the solution from deployment on most hosting solutions, because most hosts don't allow you to register DLLs unless you have a virtual or dedicated server.

This article explains how to remove that restriction using .NET. Most hosting providers allow you to use both .NET and classic ASP in their Windows Server packages. So this solution should be more "hosting friendly". The thumbnailer I setup can be found in thumbnail.aspx.

Changes

I'll focus on the changes I made to the original code so this part won't be nearly as lengthy as it was in the original article.

The call to .NET was very simple to alter. Let's take a glossed over look at the original flow.

In the original code, the upload module handles the file upload and the thumbnailing. To split out the thumbnailing, add two new steps to the flow. One that makes a call to the .NET thumbnailer, and one that reads the return JSON and reacts. The revised flow looks like this:

The Code

Read the first article ("Classic ASP Multi Upload image Gallery") for a description of the full functionality of the upload tools. I'll focus on the changes you need to make.

Changes to upload_files.js

In the original code, each time an image is uploaded, the IFrame makes a call to the function uploadDone2() on the parent (top) page and passes the return JSON as a parameter. I renamed the old uploadDone2() to thumbnailDone(), and created a new uploadDone2 as follows:

// File is uploaded, read JSON and use it to call the thumbnailer
function uploadDone2(ret) {
    var data = eval("("+ret+")"); // Read the return values from the iframe
    
    if (!data.failure) {
        var url="";
        // Assemble URL to make thumbnail.aspx call
        url += "thumbnail.aspx";
        url += "?gallery_id=" + gallery_id;
        url += "&size=" + data.size;
        url += "&file=" + data.file_name;
        //now set our IFrame target to the thumbnail page
        $("upload_target").src = url;
    }
    else if (data.failure) { //Upload failed - show user the reason.
  alert("Upload Failed: " + data.failure);
        $("uploaded_image0" + upload_counter).src = "nosign.gif";
        handleForm();
 }     
}

That's it! Our Thumbnail.aspx page is already coded to call thumbnailDone() when it completes. Here's what the code looks like:

<script type='text/javascript'>
function init() {
   if ( top.thumbnailDone )
       top.thumbnailDone( document.getElementsByTagName("body")[0].innerHTML );  
}

window.onload=init;

</script>

And here is the complete thumbnail.aspx page code:

<%@ Page Language="vb" Debug="false" Trace="false" %>
<%@ import Namespace="System.Data" %>
<%@ Import Namespace="Microsoft.VisualBasic" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
    
    function HandleThumbs() as string
        Dim galleryid As String = Request.QueryString("gallery_id")
        Dim f As String = Request.QueryString("file")
        Dim path As String = Server.MapPath(".") & "\images\" & galleryid & "\"
        Dim filepath As String = path & f
        Dim thumbroot As String = path & "thumb\"
        Dim lSize As Long = 0
        Dim Q as string = chr(34)
        Dim s as string
        
        
        '' old calls
        ''Call ThumbNail(strFileName, 32, 32, 1, 80)
        ''Call ThumbNail(strFileName, 64, 64, 1, 80)
        ''Call Thumbnail(strFileName, 96, 96, 1, 80)
        ''Call ThumbNail(strFileName, 120, 120, 1, 80)
        ''Call ThumbNail(strFileName, 240, 240, 1, 80)
        ''Call ThumbNail(strFileName, 480, 480, 1, 80)
        ''Call ThumbNail(strFileName, 640, 640, 1, 80)
        ''Call ThumbNail(strFileName, 800, 800, 1, 80)
        ''Call ThumbNail(strFileName, 960, 960, 1, 80)
        If System.IO.File.Exists(filepath) Then
            '' Generate a bunch of thumbnails, edit to suit your needs

            lSize = 32
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 48
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 64
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 70
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 96
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 120
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 240
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 480
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 640
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 760
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
            lSize = 960
            SavePhoto(filepath, thumbroot & f & "." & lSize & "x" & lSize & ".jpg", lSize)
                
                
            s = ""
            s = s & "{ "
            s = s & Q & "message" & Q & ":" & Q & "Thumbnails Complete!" & Q & ", "
            s = s & Q & "failure" & Q & ": false, " 
            s = s & Q & "file_name" & Q & ":" & Q & request.querystring("file") & Q & ", "
            s = s & Q & "size" & Q & ":" & Q & request.querystring("size") & Q & ", "
            s = s & Q & "title" & Q & ":" & Q & "" & Q & ", "
            s = s & Q & "description" & Q & ":" & Q & "" & Q & ", "
            s = s & Q & "complete" & Q & ":" & Q & "yes" & Q & " "
            s = s & "}"
        Else
            s = ""
            s = s & "{ "
            s = s & Q & "message" & Q & ":" & Q & "Path does not exist!" & Q & ", "
            s = s & Q & "failure" & Q & ": true, " 
            s = s & Q & "file_name" & Q & ":" & Q & request.querystring("file") & Q & ", "
            s = s & Q & "size" & Q & ":" & Q & request.querystring("size") & Q & ", "
            s = s & Q & "title" & Q & ":" & Q & "" & Q & ", "
            s = s & Q & "description" & Q & ":" & Q & "" & Q & ", "
            s = s & Q & "complete" & Q & ":" & Q & "yes" & Q & " "
            s = s & "}"
        End If
        
        
        HandleThumbs = s
    End Function
    '' Function lifted from 
    '' CM Image Helper Class, creates high quality images
    '' Source: <a href="http://www.aboutmydot.net/index.php/high-quality-thumbnails-vbnet">http://www.aboutmydot.net/index.php/high-quality-thumbnails-vbnet</a>
    Public Function SavePhoto(ByVal src As String, _
           ByVal dest As String, ByVal w As Integer) As Boolean
        Dim imgTmp As System.Drawing.Image
        Dim sf As Double
        Dim imgFoto As System.Drawing.Bitmap
        imgTmp = System.Drawing.Image.FromFile(src)
        If (imgTmp.Width > w) Then
            sf = imgTmp.Width / w
            imgFoto = New System.Drawing.Bitmap(w, CInt(imgTmp.Height / sf))
            Dim recDest As New System.Drawing.Rectangle(0, 0, w, imgFoto.Height)
            Dim gphCrop As System.Drawing.Graphics = _
                        System.Drawing.Graphics.FromImage(imgFoto)
            gphCrop.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
            gphCrop.CompositingQuality = _
                    System.Drawing.Drawing2D.CompositingQuality.HighQuality
            gphCrop.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High
            gphCrop.DrawImage(imgTmp, recDest, 0, 0, imgTmp.Width, 
                    imgTmp.Height, System.Drawing.GraphicsUnit.Pixel)
        Else
            imgFoto = imgTmp
        End If
        'Dim myImageCodecInfo As System.Drawing.Imaging.ImageCodecInfo
        Dim myEncoder As System.Drawing.Imaging.Encoder
        Dim myEncoderParameter As System.Drawing.Imaging.EncoderParameter
        Dim myEncoderParameters As System.Drawing.Imaging.EncoderParameters
        Dim arrayICI() As System.Drawing.Imaging.ImageCodecInfo = 
                 System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
        Dim jpegICI As System.Drawing.Imaging.ImageCodecInfo = Nothing
        Dim x As Integer = 0
        For x = 0 To arrayICI.Length - 1
            If (arrayICI(x).FormatDescription.Equals("JPEG")) Then
                jpegICI = arrayICI(x)
                Exit For
            End If
        Next
        myEncoder = System.Drawing.Imaging.Encoder.Quality
        myEncoderParameters = New System.Drawing.Imaging.EncoderParameters(1)
        myEncoderParameter = New System.Drawing.Imaging.EncoderParameter(myEncoder, 60L)
        myEncoderParameters.Param(0) = myEncoderParameter
        imgFoto.Save(dest, jpegICI, myEncoderParameters)
        imgFoto.Dispose()
        imgTmp.Dispose()
        Return True
    End Function
</script>
<html>
<head>
<script type='text/javascript'>
function init() {
   if ( top.thumbnailDone )
       top.thumbnailDone( document.getElementsByTagName("body")[0].innerHTML );  
   
}

window.onload=init;

</script>
</head>
<body id="body">
<%
if request.querystring("gallery_id")&""<>"" and request.querystring("file")<>"" then
    response.write( HandleThumbs() )
else 
    response.write( "{ 'message':'Gallery and File are required', 
                       'file':'', 'failure':true }" )
end if    
%>
</body>
</html>

Please take the time to vote and comment on this article. Thanks.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Larry Boeldt
Software Developer (Senior)
United States United States
Member
I've been in development since the late eighties. Although I've picked up many languages over the years and will likely pick up many more I have been a Microsoft BASIC programmer the whole time. Back in the early days it was on a Color Computer 3 writing articles for an enthusiast's magazine and developing solutions for color computer users. Now it is C#, VB.NET and (still) VBScript with all the fixins (ADO,XML,JSON,SQL etc...). Around 1996 I decided the internet was the way to go and dedicated myself to web development. I've been doing it ever since.
 
Two of my favorite projects are working for a little company called Nigrelli Systems and working with a team of brilliant Engineers to develop fully automated packaging systems for the food and beverage industry. The second is working on a "Burn Room" Nemschoff Chairs, again I was blessed with a team of people who knew their stuff. The burn room remains unique to this day because there are only a handfull of certified rooms in the US.
 
Bears, Beats, Battlestar Galactica

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionChanging the limit from 10 to 25. Is this possible/advisable?memberSayItAintSo2 May '13 - 12:22 
Hi,
Thanks for sharing this bit of code. Is there any reason you set the limit to 10 images? We would like to use a 25 image limit. Are you aware of any issues that should prevent this?
AnswerRe: Changing the limit from 10 to 25. Is this possible/advisable?memberLarry Boeldt8 May '13 - 15:22 
Ten kept things simple. You could running two instances of the gallery, each in in its own tab. That way you could switch between tabs while one is uploading, you can fill the other with the next batch of files. No programming/debugging required!
AnswerRe: Changing the limit from 10 to 25. Is this possible/advisable?memberLarry Boeldt20 May '13 - 17:09 
One other idea: Modern browsers (those that support HTML5 and Chrome, Firefox, IE10 & Safari) have the capability to support drag and drop from explorer to browser (yes drag and drop upload). [Here is a working example (not mine)] depending upon your ambitions, working to adapt this might give you more "bang for the buck". It might be worth exploring.
GeneralMy vote of 5memberHenryUH11 Mar '13 - 3:56 
The download has complete code
QuestionUsing the latest .NET versionmemberHenryUH11 Mar '13 - 3:51 
Compliments on your post and download, I was able to run your default settings LOCALLY
 
After I uploaded some images in the "My Own First Gallery", i noticed the following:
- I Cannot update the gallery name
- No thumbnails (just red x)
- When I click on View it responses with "No images specified in XML"
I have admin priviledges on my system
 
Once I uploaded it to the web server,
 
I have a reunion sign up where I want to make use of this function to show pictures from the last reunion (Every 5 years), see
http://www.theVeldmans.com/reunion/login.asp (password gallery, logs in as guest)

Under the Home menu I have "Gallery Test"
 
When I try to upload an image, it response with the message below, it DOES actually upload it.
In addition the spin symbol keeps spinning
 
Appreciate your comments
 
Runtime Error
Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
 
(remainder removed)
 
Thanks, Henry
AnswerRe: Using the latest .NET versionmemberLarry Boeldt11 Mar '13 - 14:47 
Hi Henry,
 
It sounds like the ASP.NET process is unable to write to the gallery folder. Usually your .NET app is configured to run under your user account in shared hosting scenarios, or if you are running an unshared server you should allow the "Network Service" account to write to your gallery/images folder.
 

 
LB
QuestionSome minor issuesmemberwaxed20 May '12 - 6:51 
Hi Larry, thanks for a great article and sample code!
I have run into some minor issues when trying to update via the admin.
 
I can view and upload images just fine! Awesome function!!
However, when I try to make a text update such as name a gallery or give a description for a gallery or an image, the update doesn't get written or breaks the gallery so the xml is no longer found.
I'm running this on my text box IIS 7. I have permissions set to modify for IUSR.
Brian Pike

AnswerRe: Some minor issuesmemberLarry Boeldt21 May '12 - 18:33 
Hi Brian, I'll take a look at this over the next couple of evenings. Are you running IIS 7 on Vista or Windows 7?
AnswerRe: Some minor issuesmemberLarry Boeldt29 May '12 - 18:48 
Hi Brian.
 
I tinkered with this a little on my Win08 Server. I had no problems running the code at first. Then I remembered that I tend to run my sites under a specific user for each site (rather than anonymous). When I switched to anonymous I was unable to write over any existing files due to permissions. You might try to setup a user account for your gallery to run under then set permissions to read/write on all gallery folders for that user while retaining at least read permissions for everyone else.
 
There may also be an issue with specific file permissions that you have to set them explicitly. It might be worth checking the individual file permissions prior to taking the more labor intensive step described above.
 
LB
GeneralEdit Gallery Error -- Object ExpectedmemberQuintin Keilloh11 Feb '12 - 22:46 
Hi there
 
Just been looking at this, and really lking the clean interface, no db is also a massive plus.
 
However have a small problem when trying to update a gallery that has been created, keep getting the error message below.
 
Any ideas? Been rooting through the code, bad cab't figure out why it thinks this value is empty.
 
I have downloaded the gallery3 scripts.
 
Message: Object expected
Line: 11
Char: 5
Code: 0
URI: http://localhost/gallery/edit_gallery.asp?gallery_id=4
GeneralRe: Edit Gallery Error -- Object ExpectedmemberLarry Boeldt15 Feb '12 - 17:55 
Hey Quintin,
 
That looks like a JavaScript error. View the source of the page that is giving you an error and search for "gallery_form" (no quotes). You should find a form with an id of gallery_form. If not that is at least a start. We then need to figure out why the form is not being created.
 
LB
QuestionError on line 136 - thumbnail.aspxmemberMember 810356522 Jul '11 - 20:20 
I have an error on line 136 of thumbnail.aspx where the code is ... imgFoto.Save(dest, jpegICI, myEncoderParameters) ... Below is the error page:
 
Server Error in '/' Application.
A generic error occurred in GDI+.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
 
Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
 
Source Error:
 
Line 134: myEncoderParameter = New System.Drawing.Imaging.EncoderParameter(myEncoder, 60L)
Line 135: myEncoderParameters.Param(0) = myEncoderParameter
Line 136: imgFoto.Save(dest, jpegICI, myEncoderParameters)
Line 137: imgFoto.Dispose()
Line 138: imgTmp.Dispose()
 

Source File: c:\inetpub\wwwroot\gallery\thumbnail.aspx Line: 136
 
Stack Trace:
 
[ExternalException (0x80004005): A generic error occurred in GDI+.]
System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) +525
ASP.thumbnail_aspx.SavePhoto(String src, String dest, Int32 w) in c:\inetpub\wwwroot\gallery\thumbnail.aspx:136
ASP.thumbnail_aspx.HandleThumbs() in c:\inetpub\wwwroot\gallery\thumbnail.aspx:33
ASP.thumbnail_aspx.__Render__control1(HtmlTextWriter __output, Control parameterContainer) in c:\inetpub\wwwroot\gallery\thumbnail.aspx:167
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +27
System.Web.UI.Control.Render(HtmlTextWriter writer) +7
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +241
System.Web.UI.Page.ProcessRequestMain() +1901
 

Version Information: Microsoft .NET Framework Version:1.0.3705.6018; ASP.NET Version:1.0.3705.6018
AnswerRe: Error on line 136 - thumbnail.aspxmemberLarry Boeldt25 Jul '11 - 18:46 
Hi, based on the error code 0x80004005 it looks like it is permission related. Since the application is ASP.NET make sure user ASP_NET has write access to the folder where your thumbnails are stored.
 
- LB -
AnswerRe: Error on line 136 - thumbnail.aspxmemberLarry Boeldt25 Jul '11 - 18:46 
Hi, based on the error code 0x80004005 it looks like it is permission related. Since the application is ASP.NET make sure user ASP_NET has write access to the folder where your thumbnails are stored.
 
LB
GeneralRe: Error on line 136 - thumbnail.aspxmemberMember 810356526 Jul '11 - 17:15 
Thank you Larry, I will try that. Thanks again!
GeneralRe: Error on line 136 - thumbnail.aspxmemberMember 810356526 Jul '11 - 22:25 
I tried that, but it seemed to still not go. I posted some questions in your original article about the gallery. I'll get those ironed out before I try to advance to your .NET application. Thanks for the help. This is fun!
QuestionDeploying IssuememberJBWills.7615 Jul '11 - 17:49 
I love the concept of this "application" but i am having some issues with it working. I started with your first version of this and then found someone else was having the same issue, no thumbnails. I have downloaded and uploaded the new version to my website. I still can not get it to work properly. I still get the spinning wheel, it does not stop. When I go to the gallery I still only get a white X for images. Any help is appreciated.
 
Where it is installed:
www.brownandwhite.org/gallery
 
The username and password is still the same.
 
Thank you,
 
Jonathan
AnswerRe: Deploying IssuememberMember 810356522 Jul '11 - 20:09 
Hi, I didn't notice this at first myself, but scroll down on the upload page, and you will see an error ... Requested URL: /gallery/thumbnail.aspx ... make sure that file is there too.
AnswerRe: Deploying IssuememberLarry Boeldt25 Jul '11 - 19:00 
Hey Johnathan,
 
It would appear that the thumbnail.aspx file is not in the /gallery/ folder based on the error message that comes up when trying to upload. You might want to try and delete the file the re-copy it from the zip file into the gallery folder. If that doesn't work we might need to dig in a little deeper and explore your web server config.
 
LB

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 19 Jul 2010
Article Copyright 2010 by Larry Boeldt
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid