?
Solved

FTP upload via asp?

Posted on 2003-03-11
16
Medium Priority
?
747 Views
Last Modified: 2008-02-01
Helo all,
well I'm stuck trying to figure out how to allow users to upload large files from within the web site...
Have tried using the standard file upload functions but IIS just pings out like crazy if the file size goes over say 20 megs or so.
I know you can set up FTP through asp as I have seen it done before but I just can't find any documentation on it.

All I need is the code for a file browse and upload using FTP.

Any help is greatly appreciated and I mean it.

Thanks in advance guys.
0
Comment
Question by:Weanerschnitzel
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 3
  • +2
16 Comments
 
LVL 2

Accepted Solution

by:
David_Cameron earned 740 total points
ID: 8116561
You can't. Sorry, but you can't.

Here is the deal. ASP is laid over the top of HTTP. When you go to upload some data (or send any data), you are generally performing an HTTP POST. All interaction in ASP is via HTTP. This means you cannot use FTP. As ASP is a server side language it cannot control FTP on the client.

To get an FTP upload system in place you need to be executing code on the client machine. This means an ActiveX control, or an applet. The process would be something like this:

- Fill in some data in the Applet/control and select a file
- FTP the file to the server
- POST (HTTP) the data to the server and an asp page, including telling the server where to find the file.
- Once the POST is complete the upload is done, so exit the applet/control

I have consistantly run into the same problems and this was the best solution I could come up with. The only problem is it involves a fair bit of work, so I never got around to implementing it.

The other question is what are you using for an upload component?  We used to use ASPSmartUpload, but found it was a real performance hog and have moved to ABCUpload.
0
 
LVL 2

Expert Comment

by:David_Cameron
ID: 8116572
Rereading your original post, I realise I was answering a slightly different question. I think all you need is one of the many FTP clients floating around the web. Get clients to install it on their PCs.
0
 

Author Comment

by:Weanerschnitzel
ID: 8116737
no you read it right the first time. I actually wrote a vb app for this but my boss doesn't want to have to email it to everyone...especially since if the ip changes then we have to send out another version of the app...and apparently the general consensus is that our clients are too stupid to have to actually enter an ip address:P

well crapola..yeah I have seen the activeX component options(mostly for sale) and I was afraid that since asp is server side that this would be the problem...but was hoping someone knew some fancy trick around it. now I just have to figure out how to write and activeX component lol
don't suppose you would know how to do that eh?
sigh
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 2

Expert Comment

by:David_Cameron
ID: 8116768
No, sorry. I looked at doing this and decided it was all too hard. I was too lazy :-).

The real problem is that ASP limits you to HTTP and to move to a more reliable protocol means you have to be running client side code.
0
 

Author Comment

by:Weanerschnitzel
ID: 8116992
no you read it right the first time. I actually wrote a vb app for this but my boss doesn't want to have to email it to everyone...especially since if the ip changes then we have to send out another version of the app...and apparently the general consensus is that our clients are too stupid to have to actually enter an ip address:P

well crapola..yeah I have seen the activeX component options(mostly for sale) and I was afraid that since asp is server side that this would be the problem...but was hoping someone knew some fancy trick around it. now I just have to figure out how to write and activeX component lol
don't suppose you would know how to do that eh?
sigh
0
 
LVL 4

Expert Comment

by:Wakie
ID: 8117054
To bottom line it for you, David_Cameron is correct.

ASP uses HTTP whereas FTP uses FTP. HTTP and FTP are two completely different protocols.

What you see when you upload files to third-party servers isn't FTP, I'd imagine the binary data was sent through the browser in these situations - but definately over HTTP.

Bear in mind, HTTP is a protocol designed for images and hypertext (HTML and other plain text formats). Although other files can be supported through this protocol, it really isn't recommended because this is the purpose of FTP (File Transfer Protocol).

Regards,
Wakie.
0
 
LVL 2

Expert Comment

by:syd108
ID: 8120014
Are you trying to address something like what yahoo does for example.
1) Let users browse their file system.
2) Upload it to your server.

YOu can do file uploads over http. But as u say the server activity will be greatly increased for large files. If you can throw lot of hardware at it you are cool.

As far as having to use ip's for ftp servers u can use friendly names instead(http://myftpserver.com:portNo) so u dont have to keep changing ip's.

regards
syd
0
 
LVL 2

Expert Comment

by:syd108
ID: 8120070
I almost forgot. There is a dll that you can buy that will let you access the FTP server from that asp and transfer the clients file to your server.
http://www.dart.com/powertcp/ftp.asp

good luck
syd
0
 
LVL 5

Expert Comment

by:prohacx
ID: 8120559
Hi Weanerschnitzel!

Yes, you cannot use FTP through ASP since it runs on top of HTTP.

BUT, you can make a file selection popup using something like:

<input type="file" id="filecontrol" name="filecontrol">

You can then upload the selected file into a database on your server (preferably SQL server) in a blob datatype field. You can use third party components, or you can write something yourself using the Scripting.Dictionary object. I made it myself easy and copied the code from someone else that provided it freely.

The only problem is that I don't find the original source anymore (it was on the internet). If you think this is what you want, reply here and I'll post my whole code, including the source (and author) of the upload class.

You can use it to write your own mp3 server for example ;-)

Bye!

0
 

Author Comment

by:Weanerschnitzel
ID: 8123488
I am very interested prohacx. Please share that.
And if this doesn't work then I'll look at a third party add-on as I obviously don't have the skills to build custom dll's yet.
0
 
LVL 2

Expert Comment

by:David_Cameron
ID: 8123614
prohacx:

None of this deals with the original problem, that uploading is inefficient and unreliable. It doesn't matter whether you are loading the files into the database or to the file system, uploading with HTTP is slow and inefficient.

Added to that, it is not reccommended that you store BLOBs in the SQL Server. They bloat the database, making it slow, and are harder to manage. The accepted practice is to save the files to disk and store a path in the database.

When using SQL Server there are some things that shouldn't be allowed: cursors, dynamic SQL and storing BLOBS.

syd108:

The question with this is the level of intergration with ASP code. The problem is that I imagine Weanerschnitzel want to do more than just run an FTP server. That means probably storing some information about the files and providing access to the files via an ASP interface. The second part of that means that at least the minimum requirement is that the asp pages need to know where to find the file. If this tool is no more than an FTP client in an control that is no more useful than say cuteFTP or any other FTP tool. It needs to be able to post some info to an ASP page as well as FTPing the file to the server. Reading the details on this tool, thsi feature doesn't appear in the list.
0
 
LVL 5

Expert Comment

by:prohacx
ID: 8126699
Hi Weanerschnitzel and David Cameron!

Yes, David is right, uploading over HTTP is not so efficient, but it does work! Storing blobs into a db maybe isn't the best way to go, but sometimes you just do it. We wrote our own internet based frontpage here for example and it combines both: we store asp files in thedb, but to speed things up, we publish them on a webserver so the db is only used for administration. All this just to demonstrate such things are possible.

Anyways, here an example of an ASP page with a file prompt:

fileSelector.asp
================

<%@ Language=VBScript %>
<%option explicit%>
<%Response.Expires = -1%>

<html>

<head>

      <title>Upload demo (fileselector.asp)</title>

      <meta http-equiv="expires" content="-1">
      <meta HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">

      <meta NAME="Author" CONTENT="Maarten De Ridder">
      <meta NAME="Keywords" CONTENT="upload demo">
      <meta NAME="Description" CONTENT="demonstrating how to upload a file over HTTP">
      <meta NAME="ROBOTS" CONTENT="INDEX, FOLLOW">
                  
</head>

<body>

<form id="frmFileUpload" name="frmFileUpload" enctype="multipart/form-data" method="post" action="uploadFile.asp">

      File:<input type="file" id="txtFile" name="txtFile" value="">

</form>

</body>
</html>


And here the page that will do the upload into the DB:

uploadFile.asp
==============

<%@ Language=VBScript %>
<%Option Explicit%>

<!-- #include file="upload.asp" -->

<%

'NOTE - YOU MUST HAVE VBSCRIPT v5.0 INSTALLED ON YOUR WEB SERVER
'         FOR THIS LIBRARY TO FUNCTION CORRECTLY. YOU CAN OBTAIN IT
'         FREE FROM MICROSOFT WHEN YOU INSTALL INTERNET EXPLORER 5.0
'         OR LATER.

' Create the FileUploader
Dim Uploader, File
Set Uploader = New FileUploader

' This starts the upload process
Uploader.Upload()

'******************************************
' Use [FileUploader object].Form to access
' additional form variables submitted with
' the file upload(s). (used below)
'******************************************

' Check if any files were uploaded
If Uploader.Files.Count = 0 Then
      Response.Write "File(s) not uploaded."
Else

      dim objConn
      dim objRs, strSQL
      set objConn = server.CreateObject("ADODB.Connection")

      objConn.Open Application("yourConnectionString")

      ' Loop through the uploaded files
      For Each File In Uploader.Files.Items
                              
            ' Open the table you are saving the file to
            Set objRs = Server.CreateObject("ADODB.Recordset")
            
            strSQL = "SELECT fileID FROM filesTable WHERE 1=2 "
            
            objRs.Open strSQL, objConn
            
            dim actionToDoIsInsert, filterID
            
            if objRs.EOF then
                  actionToDoIsInsert = true
                  filterID = -1
            else
                  actionToDoIsInsert = false
                  filterID = objRs.Fields("fileID")
            end if
            
            objRs.Close
            
            objRs.Filter = "id = " & filterID
            objRs.CursorLocation = adUseClient
            objRs.Open "filesTable", objConn, 2, 2
            
            if objRs.EOF then
                  objRs.AddNew
            end if
                  
            objRs.Fields("fileName") = File.FileName
            objRs.Fields("fileSize") = File.FileSize
            objRs.Fields("fileContentType") = File.ContentType
            
            ' Save the file to the database
            File.SaveToDatabase objRs.Fields("fileData")
                  
            ' Commit the changes and close
            objRs.Update
                        
            objRs.Close
                        
            set objRs = nothing
            
      Next
      

      objConn.Close
      
      set objConn = nothing
      
End If

set Uploader = nothing

session("remark") = "<li>File uploaded</li>"
session("errorOccured") = false


Response.Redirect "../fileSelector.asp"

%>


All we need now is to give you the include file with the core code (remember, this one is not my own programming work, I don't take any credits for this)

upload.asp
==========

<%
'***************************************
' File:        Upload.asp
' Author: Jacob "Beezle" Gilley
' Email:  avis7@airmail.net
' Date:   12/07/2000
' Comments: The code for the Upload, CByteString,
'                  CWideString      subroutines was originally
'                  written by Philippe Collignon...or so
'                  he claims. Also, I am not responsible
'                  for any ill effects this script may
'                  cause and provide this script "AS IS".
'                  Enjoy!
'****************************************

Class FileUploader
      Public  Files
      Private mcolFormElem

      Private Sub Class_Initialize()
            Set Files = Server.CreateObject("Scripting.Dictionary")
            Set mcolFormElem = Server.CreateObject("Scripting.Dictionary")
      End Sub
      
      Private Sub Class_Terminate()
            If IsObject(Files) Then
                  Files.RemoveAll()
                  Set Files = Nothing
            End If
            If IsObject(mcolFormElem) Then
                  mcolFormElem.RemoveAll()
                  Set mcolFormElem = Nothing
            End If
      End Sub

      Public Property Get Form(sIndex)
            Form = ""
            If mcolFormElem.Exists(LCase(sIndex)) Then Form = mcolFormElem.Item(LCase(sIndex))
      End Property

      Public Default Sub Upload()
            Dim biData, sInputName
            Dim nPosBegin, nPosEnd, nPos, vDataBounds, nDataBoundPos
            Dim nPosFile, nPosBound

            biData = Request.BinaryRead(Request.TotalBytes)
            nPosBegin = 1
            nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
            
            If (nPosEnd-nPosBegin) <= 0 Then Exit Sub
             
            vDataBounds = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
            nDataBoundPos = InstrB(1, biData, vDataBounds)
            
            Do Until nDataBoundPos = InstrB(biData, vDataBounds & CByteString("--"))
                  
                  nPos = InstrB(nDataBoundPos, biData, CByteString("Content-Disposition"))
                  nPos = InstrB(nPos, biData, CByteString("name="))
                  nPosBegin = nPos + 6
                  nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
                  sInputName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
                  nPosFile = InstrB(nDataBoundPos, biData, CByteString("filename="))
                  nPosBound = InstrB(nPosEnd, biData, vDataBounds)
                  
                  If nPosFile <> 0 And  nPosFile < nPosBound Then
                        Dim oUploadFile, sFileName
                        Set oUploadFile = New UploadedFile
                        
                        nPosBegin = nPosFile + 10
                        nPosEnd =  InstrB(nPosBegin, biData, CByteString(Chr(34)))
                        sFileName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
                        oUploadFile.FileName = Right(sFileName, Len(sFileName)-InStrRev(sFileName, "\"))

                        nPos = InstrB(nPosEnd, biData, CByteString("Content-Type:"))
                        nPosBegin = nPos + 14
                        nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
                        
                        oUploadFile.ContentType = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
                        
                        nPosBegin = nPosEnd+4
                        nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
                        oUploadFile.FileData = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
                        
                        If oUploadFile.FileSize > 0 Then Files.Add LCase(sInputName), oUploadFile
                  Else
                        nPos = InstrB(nPos, biData, CByteString(Chr(13)))
                        nPosBegin = nPos + 4
                        nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
                        If Not mcolFormElem.Exists(LCase(sInputName)) Then mcolFormElem.Add LCase(sInputName), CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
                  End If

                  nDataBoundPos = InstrB(nDataBoundPos + LenB(vDataBounds), biData, vDataBounds)
            Loop
      End Sub

      'String to byte string conversion
      Private Function CByteString(sString)
            Dim nIndex
            For nIndex = 1 to Len(sString)
               CByteString = CByteString & ChrB(AscB(Mid(sString,nIndex,1)))
            Next
      End Function

      'Byte string to string conversion
      Private Function CWideString(bsString)
            Dim nIndex
            CWideString =""
            For nIndex = 1 to LenB(bsString)
               CWideString = CWideString & Chr(AscB(MidB(bsString,nIndex,1)))
            Next
      End Function
End Class

Class UploadedFile
      Public ContentType
      Public FileName
      Public FileData
      
      Public Property Get FileSize()
            FileSize = LenB(FileData)
      End Property

      Public Sub SaveToDisk(sPath)
            Dim oFS, oFile
            Dim nIndex
      
            If sPath = "" Or FileName = "" Then Exit Sub
            If Mid(sPath, Len(sPath)) <> "\" Then sPath = sPath & "\"
      
            Set oFS = Server.CreateObject("Scripting.FileSystemObject")
            If Not oFS.FolderExists(sPath) Then Exit Sub
            
            Set oFile = oFS.CreateTextFile(sPath & FileName, True)
            
            For nIndex = 1 to LenB(FileData)
                oFile.Write Chr(AscB(MidB(FileData,nIndex,1)))
            Next

            oFile.Close
      End Sub
      
      Public Sub SaveToDatabase(ByRef oField)
            If LenB(FileData) = 0 Then Exit Sub
            
            If IsObject(oField) Then
                  oField.AppendChunk FileData
            End If
      End Sub

End Class
%>


And to get a file out of the db (do this in a popup window):

showfile.asp
============

<%@ Language=VBScript %>
<%option explicit%>
<%Response.Expires = -1%>

<%

dim strFileID
strFileID = Request.QueryString("fileID")

%>

<%

      server.ScriptTimeout = 1800

      if strFileID = "" then
            Response.Write "File not found<br><br><a href=""javascript: history.go(-1);"">&lt;&lt;&nbsp;back</a>"
            Response.End
      end if
      
      dim objConn
      dim objRs, strSQL
      set objConn = server.CreateObject("ADODB.Connection")
      set objRs = server.CreateObject("ADODB.Recordset")

      'Get the file out of the DB...
      strSQL = "SELECT fileName, fileSize, fileContentType, fileData FROM filesTable WHERE id = " & strFileID & " "

      objConn.Open Application("yourConnectionString")

      objRs.Open strSQL, objConn ', adOpenForwardOnly, adLockReadOnly, adCmdText

      if not objRs.EOF then
      
            if not(isnull(objRs.Fields("fileContentType"))) and not(isnull(objRs.Fields("fileData"))) and not(isnull(objRs.Fields("fileName"))) then




                  Response.Buffer = True
                  Response.Clear
                  
                  'Do NOT forget the attachment word since it will cause browsers to
                  'not display the contents of binary files...
                  
                  Response.AddHeader "Content-Disposition","attachment; filename=" & objRs.Fields("fileName")
                  Response.AddHeader "Content-Length", objRs.Fields("fileSize")
                  Response.CharSet = "UTF-8"
                  Response.ContentType = objRs.Fields("fileContentType")

                  dim stm
                  Set stm = server.CreateObject("ADODB.Stream")
                  
                  stm.Open
                  stm.Type = adTypeBinary
                  stm.Write objRs.Fields("fileData").Value
                  stm.Position = 0
                  Response.BinaryWrite stm.Read
                  Response.Flush
                  
                  stm.Close
                  set stm = nothing
                  
            end if
            
      end if
      
      objRs.Close
      objConn.Close
      
      set objRs = nothing
      set objConn = nothing
      
%>


That's all folks!

Of course you will have to adapt this code a little bit here and there. Insert your own connectionstring, and use your own table structure, these are just examples. But it is nice to store filenames, lengths, ...

Happy programming!

0
 
LVL 2

Expert Comment

by:syd108
ID: 8136912
prohacx:

1) I still agree with David large files over HTTP spells BAD IDEA. (We do it on a very beefy solaris box and still it is very slow. That is why we have FTP.)

David:
2) The ftp tool I suggested will log into the FTP server and alsp give you file listings
Check this link out. http://dotnet.dart.com/ftp/ftp.aspx

Best Regards
syd
0
 
LVL 2

Expert Comment

by:David_Cameron
ID: 8148203
syd108:

And this is different from any normal client FTP program in what way?

So you know that I am not just spouting off, I've spent the last few years working on a project management site where one of the major sections is a document management program. When storing documents people typically want to do more than just store the files. In my case the minimum would be the date stored, the person who stored the document and a list of people notified about the document upload. FTP cannot provide this.

The issue is how to link up this data with an FTP upload. There aren't a while lot of options there and they either involve forcing users into a two step process (please upload the file, then fill out the form), or to running custom code client side.
0
 

Author Comment

by:Weanerschnitzel
ID: 8227689
yeah, nice page Syd108 :)

And yeah HTTP wont work since in many cases the files will be roughly 500 megs to 10 gigs :( can you imagine the IIS timeout settings that would need to be implimented?

probably higher then the max whatever that is(it's not documented anywhere but it's a weird number...had a client set it to like I don't know 20,000 or something once cause she was tired of getting timeouts when running long sql backed .asp pages and fubar'ed the site till we figured out what she had done.)

Wish one of you guys had an example of the client side code...that wouldnt be so bad if it was like an activeX object I could have em just click yes to once...

I'm gonna go ahead and accept the answer that this ain't gonna happen and award the points for that. But if anyone runs across like I said an ActiveX component that can do this let me know I'll start up a different question and make sure you get your props :)

J
0
 

Author Comment

by:Weanerschnitzel
ID: 8227697
Not what I wanted to hear but it's 100% true so Excellent answer my friend...just wish you'd gotten around to writing that ActiveX component so I could stop lookin ;)
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have helped a lot of people on EE with their coding sources and have enjoyed near about every minute of it. Sometimes it can get a little tedious but it is always a challenge and the one thing that I always say is:   The Exchange of informatio…
I was asked about the differences between classic ASP and ASP.NET, so let me put them down here, for reference: Let's make the introductions... Classic ASP was launched by Microsoft in 1998 and dynamically generate web pages upon user interact…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question