By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,963 Members | 1,778 Online
Bytes IT Community
Submit an Article
Got Smarts?
Share your bits of IT knowledge by writing an article on Bytes.

How to upload whole files with ASP

jhardman
Expert 2.5K+
P: 3,405
Have you ever wanted to upload files through a form and thought, "I'd really like to use ASP, it surely has that capability, but the tutorial I used to learn ASP didn't mention how to do this."? Have you looked around trying to find simple solutions but didn't want to wade through pages of complex code? Have you balked at paying for premade solutions that are probably overkill for your particular project?

I'd like to walk you through the basic steps right here. Yes, it is fairly easy, and yes you can do it all with only ASP. Is it straight forward? Not exactly, but if you know the basics of manipulating long strings and using the scripting.fileSystemObject then you can do it.

Note
Much of this code has been adapted from an article from visualBuilder.com which uploads and displays files. I have made the code more linear and added the subroutine which saves the file.

Step 1: Set up
First there are two things you need to get ready before you actually work on the upload. You need a form and you need a folder. By "folder" I mean you need a folder for which the anonymous web user has permission to save files. I suggest this be a sub-folder off of your main web directory and that you not give IIS permission to execute scripts from this folder (to help prevent malicious code uploads). In my example I am using a folder called "temp" right off of my root web directory.

By "form" you may think I am being overly obvious, but there are actually a couple changes you may need to make to your basic form in order to accept file uploads. The first is a change in your form tag:
Expand|Select|Wrap|Line Numbers
  1. <form
  2.  action="upload.asp" method="post" enctype="multipart/form-data">
Notice the "enctype" attribute. If you don't have this attribute set to "multipart/form-data" then only the name of the file will be sent to the handler, in my case named "upload.asp". Then of course you need an input of type="file" to accept the upload:
Expand|Select|Wrap|Line Numbers
  1. <input type="file" name="myFileToUpload" accept="image/*">
Notice the optional "accept" attribute which you may use to filter out unacceptable file types. I have set this to accept only files with image MIME-types. This can of course be expanded or omitted completely. finish off your form in any other way you want, then continue on to the next step.

Step 2: Opening binary data posted through your form
Unlike regular form inputs with which you have likely worked in the past, files are sent as binary data and can't be manipulated exactly as a string. Also, different browsers send these files in slightly different ways, so it is probably easiest to open up all of the data posted and search through it to find how the different inputs are separated, then try to figure out which is the file. Notice that as you work with binary data, you use functions that look a lot like string manipulation functions except they all end with the letter "B". They work just the same, but they are meant to handle binary data. Try this:
Expand|Select|Wrap|Line Numbers
  1. <%
  2. Dim posi, allData, delimiter, newLineB
  3.  
  4. 'put the whole form posted into "allData"
  5. allData = request.BinaryRead(Request.TotalBytes)
  6.  
  7. 'find the first new line character in allData
  8. newLineB = chrB(13) & chrB(10)
  9. posi = instrB(1, allData, newLineB)
  10.  
  11. 'find the string which separates the different inputs
  12. delimiter = midB(allData, 1, posi-1)
  13.  
  14. 'remove first delimiter and add a new line character to the end
  15. allData = midB(allData, posi + 2, lenB(allData) - lenB(delimiter) - 2 - 4)
  16. allData = allData & newLineB %>
Step 3: Find the file data:
What you now have is a variable named 'delimiter' which holds the separator the browser used to separate different form inputs (When I tested this, I used firefox and I wrote this variable after translating it to text. It turned out to be a long series of dashes followed by a 13-digit number. I have no idea what it means) and one called "allData" which has all of the rest of the data posted to the handler. If you were to translate this data to a string and write it to the screen it would look something like this:
Expand|Select|Wrap|Line Numbers
  1. Content-Disposition: form-data; name="myTextInput"
  2.  
  3. hello world
  4. -----------------------------4564239462453
  5. Content-Disposition: form-data; name="myFileToUpload"; filename="pic.jpg"
  6. Content-Type: image/jpeg
  7.  
  8. *** a whole bunch of nonsense characters representing all the binary data of the file ***
  9. -----------------------------4564239462453
  10. Content-Disposition: form-data; name="submit"
  11.  
  12. submit
  13. -----------------------------4564239462453--
So, how do I look through this? First notice that the first line of each input is the content disposition. this includes the file name, so don't throw it away. The second line lists the content type, but it is blank unless this input is a file. So I'm going to scroll through the inputs and discard them unless this second line has a content type. I'm going to use one function which converts binary data to the equivalent ascii characters, and a subroutine which saves the file.
Expand|Select|Wrap|Line Numbers
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2.          "http://www.w3.org/TR/html4/loose.dtd">
  3.  
  4. <HTML><head><title>asp uploader</title></head><body>
  5.  
  6. <%
  7. 'find the file input, discard all others
  8. dim lstart, lfinish, disposition, fileType, content
  9. do while lenB(allData) > 0 'we're going to whittle allData down to nothing
  10.     lstart = 1
  11.     lfinish = instrB(1, allData, newLineB)
  12.  
  13.     disposition = converter(midB(allData, lstart, lfinish - lstart))
  14.     lstart = lfinish + 2
  15.  
  16.     If chr(ascB(midB(allData, lstart, 1))) = "C" then 'this input is a file
  17.         lfinish = instrB(lstart, allData, newLineB & newLineB)
  18.         'search for 2 new line characters, meaning the end of the
  19.         'content-type, saves it as fileType
  20.         fileType = trim(converter(midB(allData, lstart, lfinish - lstart)))
  21.  
  22.         'set the rest of this input as 'content'
  23.         posi = instrB(allData, newLineB & delimiter & newLineB)
  24.         content = midB(allData, lfinish + 4, posi-lfinish-4) 
  25.  
  26.         'display data for the file
  27.         response.write "<b>Content Disposition</b><br>" & vbNewLine
  28.         response.write disposition
  29.         response.write "<br>" & vbNewLine
  30.         response.write "<b>Content Type</b><br>" & vbNewline
  31.         response.write fileType
  32.         response.write "<br>" & vbNewLine
  33.         response.write "<b>Content</b><br>"
  34.  
  35.         'save file AND display it as either an <img> or <textarea>
  36.         saveFile content, disposition, fileType
  37.  
  38.         Response.Write "<br>"
  39.         Response.Write "<br>"& vbNewLine
  40.     End If
  41.  
  42.     'find the next delimiter in order to cut the first input from allData
  43.     posi = instrB(1, allData, newLineB & delimiter & newLineB)
  44.     allData = midB(allData, posi + 2 + lenB(delimiter) + 2)
  45. Loop
  46.  
  47.     Function converter(toConvert)
  48.         Dim output
  49.         Dim x
  50.  
  51.         x = 1
  52.         output = ""
  53.         'convert one character at a time to Ascii and add it to the output
  54.         do while x <= lenB(toConvert)
  55.             output = output & chr(ascB(midB(toConvert, x, 1)))
  56.             x = x + 1
  57.         loop
  58.  
  59.         converter = output
  60.     end function
  61.  
  62.     sub saveFile(content, disp, typ)
  63.         dim objFSO, objTXT, path, fileName
  64.  
  65.         'build the path to save the file
  66.         path = request.serverVariables("appl_physical_path") & "temp"
  67.  
  68.         'sometimes the filename has "\" which affects how I save it
  69.         if instr(disp, "\") > 0 then
  70.             fileName = mid(disp, instrRev(disp, "\"), len(disp)-instrRev(disp, "\"))
  71.         else
  72.             fileName = "\" & mid(disp, instr(disp, "filename=")+10, len(disp)-instr(disp, "filename=")-10) 
  73.         end if
  74.         path = path & fileName
  75.  
  76.         'save file with normal FSO and textStream methods
  77.         set objFSO = server.createObject("scripting.fileSystemObject")
  78.         set objTXT = objFSO.openTextFile (path, 2, True)
  79.         objTXT.write converter(content)
  80.         response.write "<br>(File saved as: " & path & ")<br>" & vbNewLine
  81.  
  82.         'display the file
  83.         if left(typ, 19) = "Content-Type: image" then 'file is an image
  84.             'write an image tag to the browser
  85.             response.write "<img src='/temp" & fileName & "'>"&vbNewLine
  86.         else 'file isn't an image
  87.             'write the contents of the file to a textarea in the browser
  88.             response.write "<textarea rows='10' cols='50' editable='false'>"
  89.             response.binaryWrite content
  90.             response.write "</textarea>" & vbNewline
  91.         end if
  92.     end sub
  93. %>
  94. </body>
Notice that I convert the content of the file to ascii characters and use a textstream to save it. Yes this does work for binary files. I tested it with several image files. There is a separate object called an ADO.STREAM which is supposed to be used for moving around binary files, but I couldn't get it to work for this application, and since the plain ol' textstream works OK, I will leave it like this.

Please give me any comments. I look forward to any feedback.

Jared
Aug 16 '07 #1
Share this Article
Share on Google+
18 Comments


P: 8
Thank you,

for the code - it worked indeed, even was capable of processing multipple files. But only problem with it seems to be that it gets terribly slow with file sizes larger than 100 KB. And I could not process (upload) files larger than some 200 KB. - Also it seemed that there were differences between image types, even though I did not make any systematic research with this. Browsers I used were IE7 and FireFox, both worked approximately the same .

If you could make the script faster and being capable of uploading considerably larger files, it would be important piece of code indeed!

Regards,

Matti
Sep 17 '07 #2

jhardman
Expert 2.5K+
P: 3,405
Matti,

hmm. I was aware that there was a file size limit, both with using the <input type=file> and on the server. Check your server's file upload limit (I'm not even sure where to look, but it's there somewhere) and I will research ways to get around this limitation in the script. I noticed that many of the pre-coded solutions I found on the web said that they had a way around this problem.

image type issues- this is most likely a display issue rather than an upload issue. The script just says to display any image file (whereas any other file type is not displayed) regardless of MIME type, and it is possible that some files of type "Image" will not display well in a browser. The display happens after the upload, so even if the display fails it is possible that the upload worked.

I will consider working on speed. I'll have to give it some thought. It's possible that the best way to improve speed would be to just switch to a compiled rather than scripted page, perhaps using ASP.NET

Thanks for your comments, and I will try to revise.

Jared
Sep 17 '07 #3

P: 8
Jared,

I'll wait with interest in what you will come up with! - This area of asp-upload without third party components (or even with them) have produced very much headache for many asp-developers me including some times ago. So, I am eager to see if someone can really create a simple or even really readily workable solution for this. Well, I know, there already are many pure asp-upload-classes I have also tested, of which some work relatively well (with the exception usual of file size limit pronlem). But as you neetly put in your intro to your code, they are are tend to be very complex in comparison your relatively genious solution! - Inspiration for your work!

Regards,

Matti

Matti,

hmm. I was aware that there was a file size limit, both with using the <input type=file> and on the server. Check your server's file upload limit (I'm not even sure where to look, but it's there somewhere) and I will research ways to get around this limitation in the script. I noticed that many of the pre-coded solutions I found on the web said that they had a way around this problem.

image type issues- this is most likely a display issue rather than an upload issue. The script just says to display any image file (whereas any other file type is not displayed) regardless of MIME type, and it is possible that some files of type "Image" will not display well in a browser. The display happens after the upload, so even if the display fails it is possible that the upload worked.

I will consider working on speed. I'll have to give it some thought. It's possible that the best way to improve speed would be to just switch to a compiled rather than scripted page, perhaps using ASP.NET

Thanks for your comments, and I will try to revise.

Jared
Sep 19 '07 #4

P: 4
Hi,
How to upload and display image in same page in asp.Can u suggest?
Sep 25 '07 #5

P: 8
Here is fine asp-upload class and its explanation in case you do not have proper third order com-component available in your server.

http://www.stardeveloper.com/articles/display.html?article=2001042501&page=1

And here you can download its source:
http://www.stardeveloper.com/downloads/zip/2001042501.zip

And after being capable of uploding a file into your server folder (uploaded) you can simply write:

<% response.write "<img src='/uploaded/" & fileName & "' width=100 height=200 >" %>

.. which will show your image file ( of course you can ignore width and height attributes)

Regards,

Matti

Hi,
How to upload and display image in same page in asp.Can u suggest?
Sep 25 '07 #6

P: 4
Thxs for giving that sites.But i want with out hyperlink to display image.Onace we upload image immaediatly display image inthat same page,
http://www.stardeveloper.com/article...1042501&page=1

And here you can download its source:
http://www.stardeveloper.com/downloa...2001042501.zip

And after being capable of uploding a file into your server folder (uploaded) you can simply write:

<% response.write "<img src='/uploaded/" & fileName & "' width=100 height=200 >" %>

.. which will show your image file ( of course you can ignore width and height attributes)

Regards,

Matti
Oct 1 '07 #7

jhardman
Expert 2.5K+
P: 3,405
Thxs for giving that sites.But i want with out hyperlink to display image.Onace we upload image immaediatly display image inthat same page,
this is either done with some advanced ajax or javascript, or some simple javascript which refreshes the page after uploading is done. This wouldn't necessarily be very tricky. I could probably get it to work, but it seems like more trouble than it's worth, and I'm not really a javascript expert, therefore, I won't reply with a code solution. However, the javascript forum might be able to come up with a concise solution.

Jared
Oct 1 '07 #8

P: 3
Hi Jared,
Im new in ASP.. i really like that code of yours in uploading file using asp.
Pls bear with me. I replicated your code and when i run it, it showed the input control and a button "browse". So i was abel to select a file. But how can I execute or submit it so that the file i selected will then be copied to the specific location.
Thanks!

einnor91
Oct 24 '07 #9

jhardman
Expert 2.5K+
P: 3,405
Hi Jared,
Im new in ASP.. i really like that code of yours in uploading file using asp.
Pls bear with me. I replicated your code and when i run it, it showed the input control and a button "browse". So i was abel to select a file. But how can I execute or submit it so that the file i selected will then be copied to the specific location.
Thanks!

einnor91
Not a bad question. First understand that there need to be two different files at work (as I set up the code, that is. It is possible to do it all on one file, but I prefer to separate them). The first file contains the form that the user sees. I did not try to write the entire code for the form page since I figured
  • it is not necessary to use any kind of ASP to write the form, HTML or any WYSIWYG HTML editor can write this code for you
  • I figured that it is if not necessary, then highly recommended to be HTML proficient before attempting anything with ASP
I only mentioned a couple of things about the form page because the difficult part is the second page. The first page is pretty standard HTML and it should only give you trouble if you are not HTML proficient. I highly recommend learning HTML before you try to do much more with ASP.

That said, if you are not HTML proficient, how should you code the first page? Try this very basic form page:
Expand|Select|Wrap|Line Numbers
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2.    "http://www.w3.org/TR/html4/loose.dtd">
  3. <HTML>
  4.    <HEAD>
  5.       <title>Generic From Page</title>
  6.       <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
  7.    </head>
  8.    <body>
  9.       <form action="upload.asp" method="post" enctype="multipart/form-data">
  10.          <input type="file" name="myFileToUpload" accept="image/*">
  11.          <input type="submit" name="submit" value="submit">
  12.       </form>
  13.    </body>
  14. </html>
  15.  
This basic form is set up to send a file to a page called "upload.asp" which should contain the script that accepts and saves the file. Let me know if this helps.

Jared
Oct 24 '07 #10

P: 48
Iwas wondering why would you go for such a hastle when the file Upload feature is inbuilt in ASP.NET

On the Page itself No Form Declaration is Required only a ine Liner as below:
Expand|Select|Wrap|Line Numbers
  1. <asp:FileUpload ID="FileUpload1" runat="server" />
  2. <asp:Button ID="Button1" runat="server" Text="Upload File" />
On on the VB File:
Expand|Select|Wrap|Line Numbers
  1. Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  2. FileUpload1.SaveAs("<PathtosaveFile>\"  & FileUpload1.FileName)
  3. End Sub
  4.  
I Understand that you could have existing Classic ASP COdes but you could always have a single ASP.NET project with a single page just for the upload purpose....,and you could upload any kind of Files You feel like.

The Only Additional Requirement is install Dot Net Framework 2.0.

I have Cut Pasted all the sections below as it is in my test code:

File:web.config:
Expand|Select|Wrap|Line Numbers
  1. <?xml version="1.0"?>
  2. <configuration>
  3.     <appSettings/>
  4.     <connectionStrings/>
  5.     <system.web>
  6.         <compilation debug="true" strict="false" explicit="true"/>
  7.         <pages>
  8.             <namespaces>
  9.                 <clear/>
  10.                 <add namespace="System"/>
  11.                 <add namespace="System.Collections"/>
  12.                 <add namespace="System.Collections.Specialized"/>
  13.                 <add namespace="System.Configuration"/>
  14.                 <add namespace="System.Text"/>
  15.                 <add namespace="System.Text.RegularExpressions"/>
  16.                 <add namespace="System.Web"/>
  17.                 <add namespace="System.Web.Caching"/>
  18.                 <add namespace="System.Web.SessionState"/>
  19.                 <add namespace="System.Web.Security"/>
  20.                 <add namespace="System.Web.Profile"/>
  21.                 <add namespace="System.Web.UI"/>
  22.                 <add namespace="System.Web.UI.WebControls"/>
  23.                 <add namespace="System.Web.UI.WebControls.WebParts"/>
  24.                 <add namespace="System.Web.UI.HtmlControls"/>
  25.             </namespaces>
  26.         </pages>
  27.         <authentication mode="Windows"/>
  28.     </system.web>
  29. </configuration>
File:Default.aspx:
Expand|Select|Wrap|Line Numbers
  1. <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4.  
  5. <html xmlns="http://www.w3.org/1999/xhtml" >
  6. <head runat="server">
  7.     <title>Untitled Page</title>
  8. </head>
  9. <body>
  10.     <form id="form1" runat="server">
  11.     <div>
  12.         <asp:FileUpload ID="FileUpload1" runat="server" /><br />
  13.         <br />
  14.         <asp:Button ID="Button1" runat="server" Text="Button" />&nbsp;</div>
  15.     </form>
  16. </body>
  17. </html>
  18.  
File:Default.vb:
Expand|Select|Wrap|Line Numbers
  1. Partial Class _Default
  2.     Inherits System.Web.UI.Page
  3.  
  4.     Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  5.         FileUpload1.SaveAs("C:\" & FileUpload1.FileName)
  6.     End Sub
  7. End Class
  8.  
Oct 31 '07 #11

jhardman
Expert 2.5K+
P: 3,405
I was wondering why would you go for such a hassle when the file Upload feature is inbuilt in ASP.NET
Point taken. You might as well ask why we do anything with asp, it could be argued that just about anything can be done easier with .NET

Rather than try to answer that, allow me to point out that this forum is dedicated to "classic" asp questions, so if someone asks me how to upload files (and many have) I will come up with an asp solution because it is the only answer appropriate for the location (besides saying "maybe you should try .NET instead" and you already said that for me).

And yes, I can come up with several reasons that I still use classic ASP rather than .NET.

Jared
Nov 2 '07 #12

P: 1
Matti,

hmm. I was aware that there was a file size limit, both with using the <input type=file> and on the server. Check your server's file upload limit (I'm not even sure where to look, but it's there somewhere) and I will research ways to get around this limitation in the script. I noticed that many of the pre-coded solutions I found on the web said that they had a way around this problem.

Jared
Hi,
IIS 6.0 on Windows 2003 has a file named metabase.xml which resides in the folder C:\Windows\system32\inetsrv . By default, this file has this entry:

AspMaxRequestEntityAllowed = "204800"

This limits upload size to 204,800 bytes. You can change that to a large value (such as 2000000000 for 2 gigabytes) to allow your Windows 2003 server to accept large uploads.

If your server does not allow the Metabase Edit-While-Running feature, you will need to stop the IIS service before you can save the metabase.xml file.
or
Goto IIS Properties and chk "Enable Direct Metabase Edit"


but my problem is that on some systems it is uploading successfully with size AspMaxRequestEntityAllowed = "204800" but on some other Request.Binaryread returns empty, though file were of same size
are there any other IIS settings or antivirus or nay thing else that limits request.binaryread
my os is win2003 server
Nov 27 '07 #13

jhardman
Expert 2.5K+
P: 3,405
but my problem is that on some systems it is uploading successfully with size AspMaxRequestEntityAllowed = "204800" but on some other Request.Binaryread returns empty, though file were of same size
are there any other IIS settings or antivirus or nay thing else that limits request.binaryread
my os is win2003 server
Do you get this problem consistantly or sporadically?

Thanks for your solution to the file size limit, btw. I was thinking that some browsers also limit upload sizes (the file input is one of the least consistantly handled HTML tags) and this might be what you are experiencing, but I'm not even sure where to check.

Jared
Nov 27 '07 #14

danp129
Expert 100+
P: 321
Hate to bump old stuff but saw new referral to this thread...

Using FSO is slow and resource intensive. I would recommend something that uses adodb.stream object for writing the files. I'm fairly certain it gets around the size issue and it's MUCH faster and less CPU intensive.

http://www.taka.nl/programming/asp/comparing_fileupload.asp

If you look at that chart you can see a speed comparison of using FSO vs ADO stream. FSO being 'ASP Emporium' and 'ASP101'.
Oct 9 '08 #15

jhardman
Expert 2.5K+
P: 3,405
Hate to bump old stuff but saw new referral to this thread...

Using FSO is slow and resource intensive. I would recommend something that uses adodb.stream object for writing the files. I'm fairly certain it gets around the size issue and it's MUCH faster and less CPU intensive.

http://www.taka.nl/programming/asp/comparing_fileupload.asp

If you look at that chart you can see a speed comparison of using FSO vs ADO stream. FSO being 'ASP Emporium' and 'ASP101'.
I tried to get ado.stream going earlier because obviously the fso isn't the right way to go, I just couldn't ever get it to work, and since ASP really is a dying technology, I was happy to leave it at that.

The size limitations we ran into all seemed to be in regards to the upload process, so I'm hesitant to think switching to ado.stream would make any difference with that issue.

Jared
Oct 9 '08 #16

danp129
Expert 100+
P: 321
I know at least one pure script one that used ADO I tried worked w/o modifying IIS.
Oct 10 '08 #17

jhardman
Expert 2.5K+
P: 3,405
I know at least one pure script one that used ADO I tried worked w/o modifying IIS.
Do you have a code snippet or a link?

Jared
Oct 10 '08 #18

P: 1
I really thank you!
You can't imagine how usefull your code was! now I get how it Works
Even you introduce me to the metadata thing
For real Thank you
Aug 14 '18 #19