How to upload whole files with ASP

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jhardman
    Recognized Expert Specialist
    • Jan 2007
    • 3405

    How to upload whole files with ASP

    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.fileS ystemObject then you can do it.

    Note
    Much of this code has been adapted from an article from visualBuilder.c om 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:
    Code:
    <form
     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:
    Code:
    <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:
    [code=asp]<%
    Dim posi, allData, delimiter, newLineB

    'put the whole form posted into "allData"
    allData = request.BinaryR ead(Request.Tot alBytes)

    'find the first new line character in allData
    newLineB = chrB(13) & chrB(10)
    posi = instrB(1, allData, newLineB)

    'find the string which separates the different inputs
    delimiter = midB(allData, 1, posi-1)

    'remove first delimiter and add a new line character to the end
    allData = midB(allData, posi + 2, lenB(allData) - lenB(delimiter) - 2 - 4)
    allData = allData & newLineB %>[/code]

    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:
    Code:
    Content-Disposition: form-data; name="myTextInput"
    
    hello world
    -----------------------------4564239462453
    Content-Disposition: form-data; name="myFileToUpload"; filename="pic.jpg"
    Content-Type: image/jpeg
    
    *** a whole bunch of nonsense characters representing all the binary data of the file ***
    -----------------------------4564239462453
    Content-Disposition: form-data; name="submit"
    
    submit
    -----------------------------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.
    [code=asp]<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

    <HTML><head><ti tle>asp uploader</title></head><body>

    <%
    'find the file input, discard all others
    dim lstart, lfinish, disposition, fileType, content
    do while lenB(allData) > 0 'we're going to whittle allData down to nothing
    lstart = 1
    lfinish = instrB(1, allData, newLineB)

    disposition = converter(midB( allData, lstart, lfinish - lstart))
    lstart = lfinish + 2

    If chr(ascB(midB(a llData, lstart, 1))) = "C" then 'this input is a file
    lfinish = instrB(lstart, allData, newLineB & newLineB)
    'search for 2 new line characters, meaning the end of the
    'content-type, saves it as fileType
    fileType = trim(converter( midB(allData, lstart, lfinish - lstart)))

    'set the rest of this input as 'content'
    posi = instrB(allData, newLineB & delimiter & newLineB)
    content = midB(allData, lfinish + 4, posi-lfinish-4)

    'display data for the file
    response.write "<b>Content Disposition</b><br>" & vbNewLine
    response.write disposition
    response.write "<br>" & vbNewLine
    response.write "<b>Content Type</b><br>" & vbNewline
    response.write fileType
    response.write "<br>" & vbNewLine
    response.write "<b>Content </b><br>"

    'save file AND display it as either an <img> or <textarea>
    saveFile content, disposition, fileType

    Response.Write "<br>"
    Response.Write "<br>"& vbNewLine
    End If

    'find the next delimiter in order to cut the first input from allData
    posi = instrB(1, allData, newLineB & delimiter & newLineB)
    allData = midB(allData, posi + 2 + lenB(delimiter) + 2)
    Loop

    Function converter(toCon vert)
    Dim output
    Dim x

    x = 1
    output = ""
    'convert one character at a time to Ascii and add it to the output
    do while x <= lenB(toConvert)
    output = output & chr(ascB(midB(t oConvert, x, 1)))
    x = x + 1
    loop

    converter = output
    end function

    sub saveFile(conten t, disp, typ)
    dim objFSO, objTXT, path, fileName

    'build the path to save the file
    path = request.serverV ariables("appl_ physical_path") & "temp"

    'sometimes the filename has "\" which affects how I save it
    if instr(disp, "\") > 0 then
    fileName = mid(disp, instrRev(disp, "\"), len(disp)-instrRev(disp, "\"))
    else
    fileName = "\" & mid(disp, instr(disp, "filename=")+10 , len(disp)-instr(disp, "filename=" )-10)
    end if
    path = path & fileName

    'save file with normal FSO and textStream methods
    set objFSO = server.createOb ject("scripting .fileSystemObje ct")
    set objTXT = objFSO.openText File (path, 2, True)
    objTXT.write converter(conte nt)
    response.write "<br>(File saved as: " & path & ")<br>" & vbNewLine

    'display the file
    if left(typ, 19) = "Content-Type: image" then 'file is an image
    'write an image tag to the browser
    response.write "<img src='/temp" & fileName & "'>"&vbNewL ine
    else 'file isn't an image
    'write the contents of the file to a textarea in the browser
    response.write "<textarea rows='10' cols='50' editable='false '>"
    response.binary Write content
    response.write "</textarea>" & vbNewline
    end if
    end sub
    %>
    </body>[/code]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
  • mylo1968
    New Member
    • Oct 2006
    • 8

    #2
    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

    Comment

    • jhardman
      Recognized Expert Specialist
      • Jan 2007
      • 3405

      #3
      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

      Comment

      • mylo1968
        New Member
        • Oct 2006
        • 8

        #4
        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

        Originally posted by jhardman
        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

        Comment

        • kethireddy
          New Member
          • Sep 2007
          • 4

          #5
          Hi,
          How to upload and display image in same page in asp.Can u suggest?

          Comment

          • mylo1968
            New Member
            • Oct 2006
            • 8

            #6
            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.stardevelop er.com/articles/display.html?ar ticle=200104250 1&page=1

            And here you can download its source:
            http://www.stardevelop er.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

            Originally posted by kethireddy
            Hi,
            How to upload and display image in same page in asp.Can u suggest?

            Comment

            • kethireddy
              New Member
              • Sep 2007
              • 4

              #7
              Thxs for giving that sites.But i want with out hyperlink to display image.Onace we upload image immaediatly display image inthat same page,


              And here you can download its source:


              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

              Comment

              • jhardman
                Recognized Expert Specialist
                • Jan 2007
                • 3405

                #8
                Originally posted by kethireddy
                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

                Comment

                • einnor91
                  New Member
                  • Oct 2007
                  • 3

                  #9
                  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

                  Comment

                  • jhardman
                    Recognized Expert Specialist
                    • Jan 2007
                    • 3405

                    #10
                    Originally posted by einnor91
                    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:
                    Code:
                    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                       "http://www.w3.org/TR/html4/loose.dtd">
                    <HTML>
                       <HEAD>
                          <title>Generic From Page</title>
                          <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
                       </head>
                       <body>
                          <form action="upload.asp" method="post" enctype="multipart/form-data">
                             <input type="file" name="myFileToUpload" accept="image/*">
                             <input type="submit" name="submit" value="submit">
                          </form>
                       </body>
                    </html>
                    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

                    Comment

                    • shrimant
                      New Member
                      • Sep 2007
                      • 48

                      #11
                      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:
                      Code:
                      <asp:FileUpload ID="FileUpload1" runat="server" />
                      <asp:Button ID="Button1" runat="server" Text="Upload File" />
                      On on the VB File:
                      Code:
                      Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
                      FileUpload1.SaveAs("<PathtosaveFile>\"  & FileUpload1.FileName)
                      End Sub
                      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 :
                      Code:
                      <?xml version="1.0"?>
                      <configuration>
                      	<appSettings/>
                      	<connectionStrings/>
                      	<system.web>
                      		<compilation debug="true" strict="false" explicit="true"/>
                      		<pages>
                      			<namespaces>
                      				<clear/>
                      				<add namespace="System"/>
                      				<add namespace="System.Collections"/>
                      				<add namespace="System.Collections.Specialized"/>
                      				<add namespace="System.Configuration"/>
                      				<add namespace="System.Text"/>
                      				<add namespace="System.Text.RegularExpressions"/>
                      				<add namespace="System.Web"/>
                      				<add namespace="System.Web.Caching"/>
                      				<add namespace="System.Web.SessionState"/>
                      				<add namespace="System.Web.Security"/>
                      				<add namespace="System.Web.Profile"/>
                      				<add namespace="System.Web.UI"/>
                      				<add namespace="System.Web.UI.WebControls"/>
                      				<add namespace="System.Web.UI.WebControls.WebParts"/>
                      				<add namespace="System.Web.UI.HtmlControls"/>
                      			</namespaces>
                      		</pages>
                      		<authentication mode="Windows"/>
                      	</system.web>
                      </configuration>
                      File:Default.as px:
                      Code:
                      <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
                      
                      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                      
                      <html xmlns="http://www.w3.org/1999/xhtml" >
                      <head runat="server">
                          <title>Untitled Page</title>
                      </head>
                      <body>
                          <form id="form1" runat="server">
                          <div>
                              <asp:FileUpload ID="FileUpload1" runat="server" /><br />
                              <br />
                              <asp:Button ID="Button1" runat="server" Text="Button" />&nbsp;</div>
                          </form>
                      </body>
                      </html>
                      File:Default.vb :
                      Code:
                      Partial Class _Default
                          Inherits System.Web.UI.Page
                      
                          Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
                              FileUpload1.SaveAs("C:\" & FileUpload1.FileName)
                          End Sub
                      End Class

                      Comment

                      • jhardman
                        Recognized Expert Specialist
                        • Jan 2007
                        • 3405

                        #12
                        Originally posted by shrimant
                        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

                        Comment

                        • S4Sadia
                          New Member
                          • Nov 2007
                          • 1

                          #13
                          Originally posted by jhardman
                          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\syst em32\inetsrv . By default, this file has this entry:

                          AspMaxRequestEn tityAllowed = "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 AspMaxRequestEn tityAllowed = "204800" but on some other Request.Binaryr ead returns empty, though file were of same size
                          are there any other IIS settings or antivirus or nay thing else that limits request.binaryr ead
                          my os is win2003 server

                          Comment

                          • jhardman
                            Recognized Expert Specialist
                            • Jan 2007
                            • 3405

                            #14
                            Originally posted by S4Sadia
                            but my problem is that on some systems it is uploading successfully with size AspMaxRequestEn tityAllowed = "204800" but on some other Request.Binaryr ead returns empty, though file were of same size
                            are there any other IIS settings or antivirus or nay thing else that limits request.binaryr ead
                            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

                            Comment

                            • danp129
                              Recognized Expert Contributor
                              • Jul 2006
                              • 323

                              #15
                              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_fileu pload.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'.

                              Comment

                              Working...