Connecting Tech Pros Worldwide Help | Site Map

Download file to client after form submission

Newbie
 
Join Date: Aug 2009
Posts: 4
#1: Aug 24 '09
Hi, I'm building a simple online image gallery that allows users to download full size images for free with one condition - they must submit their name and why the chose the image. I want to use a very simple form for this. I would like to send the file back to the user after the information they submitted is logged into a sql server database.

How can I make sure to send the file only after a user submits the form?
And how can I prevent the user from downloading the file directly? Maybe use the transmitfile() after form validation?

Help is greatly appreciated!
best answer - posted by Frinavale
Quote:

Originally Posted by captainB View Post

Frinavale - Thank you for such a detailed response!
Let me see if I am implementing your suggestion correctly:
I have a gallery page with thumbnails, and each thumbnail is a link to a page - download.aspx - which shows the select thumbnail and a simple form with name, city, state and comments fields. The form's submit button uses POST to send the form back to the server - the url it uses is download.aspx.cs, which has methods to save the fields to a sql server database.

I wasn't quite suggesting this.

I was suggesting creating an ASPX page that would not return HTML...instead it would return a "thumbnail" version of the image.

This "ASPX" page would be called something like "Thumbnail.aspx" and would return a very low resolution image of the original image.

This page would have a Response.ContentType="image/jpg". It would read the image into memory and write a low resolution version of the image directly to the output stream.

For example, the following ASPX page will read return an low-resolution thumbnail image when called.
Expand|Select|Wrap|Line Numbers
  1. Private _imagePath As String = "~/images/"
  2. Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  3.  
  4.         'Changing the page's content type to display images
  5.         Response.ContentType = "image/jpg"
  6.  
  7.         'Retrieving the name of the image to display 
  8.         '(Yours is stored in Session)
  9.          imageName = Request.QueryString("imgName")
  10.  
  11.          If String.IsNullOrEmpty(imageName) = False Then
  12.                 'Retrieving the picture
  13.                 imageUrl = String.Format("{0}{1}", _imagePath, imageName)
  14.  
  15.                 If IO.File.Exists(Server.MapPath(imageUrl)) Then
  16.                      Dim fullSizeImg As System.Drawing.Image
  17.                      fullSizeImg = System.Drawing.Image.FromFile(Server.MapPath(imageUrl))
  18.                      ShowThumbnail(fullSizeImg )
  19.                      ' cleaning up the full size image
  20.                       fullSizeImg.Dispose()
  21.                End If
  22.          End If
  23.  
  24. End Sub
  25.  
  26. Private Sub ShowThumbnail(ByVal imageToShow As System.Drawing.Image)
  27.  
  28.         Dim imageWidth As Integer = imageToShow.Width
  29.         Dim imageHeight As Integer = imageToShow.Height
  30.  
  31.         Dim newWidth As Integer
  32.         Dim newHeight As Integer
  33.  
  34.  
  35.         'Shrinking the image if it is large than the thumbnail dimensions
  36.         If imageHeight > _maxHeight Or imageWidth > _maxWidth Then
  37.             Dim scaleFactor As Double
  38.             'determine how to scale image: by height or width
  39.             Dim deltaWidth As Integer = imageWidth - _maxWidth
  40.             Dim deltaHeight As Integer = imageHeight - _maxHeight
  41.  
  42.             If deltaHeight > deltaWidth Then
  43.                 'difference between the max height and the height of the picture is greater
  44.                 'that the difference between the max width and the width of the picture, so scale by height
  45.                 scaleFactor = _maxHeight / imageHeight
  46.             Else
  47.                 'difference between the max width and the width of the picture is greater
  48.                 'that the difference between the max height and the height of the picture, so scale by width
  49.                 scaleFactor = _maxWidth / imageWidth
  50.             End If
  51.             newWidth = CType(scaleFactor * imageWidth, Integer)
  52.             newHeight = CType(scaleFactor * imageHeight, Integer)
  53.         End If
  54.  
  55.         'Creating the thumbnail image
  56.         Dim thumbnailImage As System.Drawing.Image
  57.         thumbnailImage = imageToShow.GetThumbnailImage(newWidth, newHeight, New System.Drawing.Image.GetThumbnailImageAbort(Function() False), IntPtr.Zero)
  58.  
  59.         'Writing the thumbnail image directly to the output stream
  60.         thumbnailImage.Save(Response.OutputStream, ImageFormat.Jpeg)
  61.  
  62.         'cleaning up the thumbnail image
  63.         thumbnailImage.Dispose()
  64. End Sub
Now instead of having the image URL as a path to the image, you'd have the Image URL to the path of the Thumbnail.aspx page.

eg:
<asp:Image ImageURL="Thumbnail.aspx?thePicture.jpg" ID="theLowResImage" />



However, if the user was allowed to download the full size image the Thumbnail.aspx page will return the full size image instead of the thumbnail image.

You'd check your 'grant_download' Session variable to see if which version to return to the user.

Quote:

Originally Posted by captainB View Post

After the save is successful, I set a session parameter called ["grant_download"] with a value of <filename>.
Now, lets assume the user has one filename in this variable, and would like to download another image. What would be a good way to maintain a list of filenames? I could concatenate to the variable like so: "image01.jpg_image02.jpg_image03.jpg" and slice the string (using the underscore character) into an array. I'd do this with each download request to check if the file is in the array and is permitted to download.

You can store Arrays in session...............

Quote:

Originally Posted by captainB View Post

Since I'm using session variables, what would happen when the session ends as a result of a timeout?

Then the user would no longer be allowed to download the full size images.


In this case you'll have to go with your plan B:
Quote:

Originally Posted by captainB View Post

One idea I had was to save these variables in the database along with the client's IP, and maybe compare the file requested and IP to a realtime request, which might eliminate the session timeout problem. However clients with dynamic IPs may cause a problem with this logic.

However, your Plan B is a little over complicated...I'd use Persistent Cookies instead ;)
Member
 
Join Date: May 2009
Location: Goregaon, मुंबई IN :)
Posts: 85
#2: Aug 25 '09

re: Download file to client after form submission


just use simple if condition

Expand|Select|Wrap|Line Numbers
  1. if user has submitted name
  2.        then download the file
  3. else
  4.         show error
Newbie
 
Join Date: Aug 2009
Posts: 4
#3: Aug 25 '09

re: Download file to client after form submission


NitinSawant - Thanks for the reply!

I used a rather simple IF logic and it works:
1. user submits form back to server - download.aspx page.
2. download.aspx.cs (code behind) file checks the form fields (here's the IF logic).
3. if form fields are ok, use the Response.Transmitfile() method to download the file to the user.


But here's where it is getting a bit more complicated-
Instead of sending the file back in the response to the form submission, I would like to send back a "your download will begin shortly" page which will send another request to download the file after it is loaded on the browser (javascript timer?) using a http handler, perhaps.

How will the http handler know that the user did in fact submit a form with valid fields for the requested file?

Thanks, I really appreciate you help!
Frinavale's Avatar
Site Moderator
 
Join Date: Oct 2006
Location: The Great White North
Posts: 5,066
#4: Aug 27 '09

re: Download file to client after form submission


I would recommend using an ASPX page to return a "thumbnail" size photo. That way the user won't be able to download the whole image just by viewing your initial page.

Now if the user wants to open the full size image, they provide their information and click the submit button.

The server will validate the user's information, set a session variable indicating that they're permitted to download the file that they've picked.

I would use Ajax here, that way when the user clicks the Submit button the whole page isn't updated when the validation/session-setting-stuff is done.

When the Ajax request returns it'll either display an error message, or execute a bit of JavaScript that will open a new page, linking the user to another ASPX page that will either return the full size image (if the session variable has been set) or it'll return a message stating that they have to successfully fill out the form before they're allowed to download the picture.

To execute the JavaScript upon return will require you to use the AJAX.NET library. You can specify a JavaScript method to execute whenever the Ajax Request is finished.

To do this you'd use the PageRequestManager and supply an "end request event handler method"......

Eg (JavaScript):
Expand|Select|Wrap|Line Numbers
  1. var prm = Sys.WebForms.PageRequestManager.getInstance();
  2. prm.add_endRequest(endRequestEventHandler);
  3. function beginRequestEventHandler()
  4.   //.....
  5. }
Using the PageRequestManager might not be the best choice here....you could create a Behavior.js file for the page....

There's a bunch of different ways to do this.

But really you should be using ASPX pages to return the images (don't just use a URL to the photo) so that you can add security to your images.

After that, we can take a look at how to allow the user to download the image after they've submitted the forum......
Newbie
 
Join Date: Aug 2009
Posts: 4
#5: Aug 28 '09

re: Download file to client after form submission


Frinavale - Thank you for such a detailed response!
Let me see if I am implementing your suggestion correctly:
I have a gallery page with thumbnails, and each thumbnail is a link to a page - download.aspx - which shows the select thumbnail and a simple form with name, city, state and comments fields. The form's submit button uses POST to send the form back to the server - the url it uses is download.aspx.cs, which has methods to save the fields to a sql server database.
After the save is successful, I set a session parameter called ["grant_download"] with a value of <filename>.
Now, lets assume the user has one filename in this variable, and would like to download another image. What would be a good way to maintain a list of filenames? I could concatenate to the variable like so: "image01.jpg_image02.jpg_image03.jpg" and slice the string (using the underscore character) into an array. I'd do this with each download request to check if the file is in the array and is permitted to download.

Since I'm using session variables, what would happen when the session ends as a result of a timeout?
One idea I had was to save these variables in the database along with the client's IP, and maybe compare the file requested and IP to a realtime request, which might eliminate the session timeout problem. However clients with dynamic IPs may cause a problem with this logic.

Any ideas?

Thanks!
Frinavale's Avatar
Site Moderator
 
Join Date: Oct 2006
Location: The Great White North
Posts: 5,066
#6: Aug 28 '09

re: Download file to client after form submission


Quote:

Originally Posted by captainB View Post

Frinavale - Thank you for such a detailed response!
Let me see if I am implementing your suggestion correctly:
I have a gallery page with thumbnails, and each thumbnail is a link to a page - download.aspx - which shows the select thumbnail and a simple form with name, city, state and comments fields. The form's submit button uses POST to send the form back to the server - the url it uses is download.aspx.cs, which has methods to save the fields to a sql server database.

I wasn't quite suggesting this.

I was suggesting creating an ASPX page that would not return HTML...instead it would return a "thumbnail" version of the image.

This "ASPX" page would be called something like "Thumbnail.aspx" and would return a very low resolution image of the original image.

This page would have a Response.ContentType="image/jpg". It would read the image into memory and write a low resolution version of the image directly to the output stream.

For example, the following ASPX page will read return an low-resolution thumbnail image when called.
Expand|Select|Wrap|Line Numbers
  1. Private _imagePath As String = "~/images/"
  2. Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  3.  
  4.         'Changing the page's content type to display images
  5.         Response.ContentType = "image/jpg"
  6.  
  7.         'Retrieving the name of the image to display 
  8.         '(Yours is stored in Session)
  9.          imageName = Request.QueryString("imgName")
  10.  
  11.          If String.IsNullOrEmpty(imageName) = False Then
  12.                 'Retrieving the picture
  13.                 imageUrl = String.Format("{0}{1}", _imagePath, imageName)
  14.  
  15.                 If IO.File.Exists(Server.MapPath(imageUrl)) Then
  16.                      Dim fullSizeImg As System.Drawing.Image
  17.                      fullSizeImg = System.Drawing.Image.FromFile(Server.MapPath(imageUrl))
  18.                      ShowThumbnail(fullSizeImg )
  19.                      ' cleaning up the full size image
  20.                       fullSizeImg.Dispose()
  21.                End If
  22.          End If
  23.  
  24. End Sub
  25.  
  26. Private Sub ShowThumbnail(ByVal imageToShow As System.Drawing.Image)
  27.  
  28.         Dim imageWidth As Integer = imageToShow.Width
  29.         Dim imageHeight As Integer = imageToShow.Height
  30.  
  31.         Dim newWidth As Integer
  32.         Dim newHeight As Integer
  33.  
  34.  
  35.         'Shrinking the image if it is large than the thumbnail dimensions
  36.         If imageHeight > _maxHeight Or imageWidth > _maxWidth Then
  37.             Dim scaleFactor As Double
  38.             'determine how to scale image: by height or width
  39.             Dim deltaWidth As Integer = imageWidth - _maxWidth
  40.             Dim deltaHeight As Integer = imageHeight - _maxHeight
  41.  
  42.             If deltaHeight > deltaWidth Then
  43.                 'difference between the max height and the height of the picture is greater
  44.                 'that the difference between the max width and the width of the picture, so scale by height
  45.                 scaleFactor = _maxHeight / imageHeight
  46.             Else
  47.                 'difference between the max width and the width of the picture is greater
  48.                 'that the difference between the max height and the height of the picture, so scale by width
  49.                 scaleFactor = _maxWidth / imageWidth
  50.             End If
  51.             newWidth = CType(scaleFactor * imageWidth, Integer)
  52.             newHeight = CType(scaleFactor * imageHeight, Integer)
  53.         End If
  54.  
  55.         'Creating the thumbnail image
  56.         Dim thumbnailImage As System.Drawing.Image
  57.         thumbnailImage = imageToShow.GetThumbnailImage(newWidth, newHeight, New System.Drawing.Image.GetThumbnailImageAbort(Function() False), IntPtr.Zero)
  58.  
  59.         'Writing the thumbnail image directly to the output stream
  60.         thumbnailImage.Save(Response.OutputStream, ImageFormat.Jpeg)
  61.  
  62.         'cleaning up the thumbnail image
  63.         thumbnailImage.Dispose()
  64. End Sub
Now instead of having the image URL as a path to the image, you'd have the Image URL to the path of the Thumbnail.aspx page.

eg:
<asp:Image ImageURL="Thumbnail.aspx?thePicture.jpg" ID="theLowResImage" />



However, if the user was allowed to download the full size image the Thumbnail.aspx page will return the full size image instead of the thumbnail image.

You'd check your 'grant_download' Session variable to see if which version to return to the user.

Quote:

Originally Posted by captainB View Post

After the save is successful, I set a session parameter called ["grant_download"] with a value of <filename>.
Now, lets assume the user has one filename in this variable, and would like to download another image. What would be a good way to maintain a list of filenames? I could concatenate to the variable like so: "image01.jpg_image02.jpg_image03.jpg" and slice the string (using the underscore character) into an array. I'd do this with each download request to check if the file is in the array and is permitted to download.

You can store Arrays in session...............

Quote:

Originally Posted by captainB View Post

Since I'm using session variables, what would happen when the session ends as a result of a timeout?

Then the user would no longer be allowed to download the full size images.


In this case you'll have to go with your plan B:
Quote:

Originally Posted by captainB View Post

One idea I had was to save these variables in the database along with the client's IP, and maybe compare the file requested and IP to a realtime request, which might eliminate the session timeout problem. However clients with dynamic IPs may cause a problem with this logic.

However, your Plan B is a little over complicated...I'd use Persistent Cookies instead ;)
Reply