Solved

File Path as Parameter

Posted on 2003-10-30
26
605 Views
Last Modified: 2012-06-27
Re: http://www.experts-exchange.com/Web/Web_Languages/ASP/Q_20780828.html

Okay, I'm trying to pull this off - and believe it or not, I'm stumped.

I have download.asp that streams documents that users click on, and records the download in a db.

Problem: The documents are in a number of different folders, but the file location is hard coded into download.asp. From the previous Q, it seems that passing the location of the file as a parameter to download.asp is the best bet - but I can't figure out how to get it to function properly.

It also seems odd, because the links in the pages are of the type:
<a href="../download.asp?file=somefolder/anotherfolder/somedoc.doc">
So - doesn't that mean that the location of the file should be known, and can easily be inserted into download.asp on the fly?

download.asp is:
************

<%
response.buffer=true

Function downloadFile( strFile, strDownloadFilename, strPath )

     Dim strFilename,objStream,objFilesystem,objFilestream
     Dim intFileLength
     ' get path of specified file
     strFilename = Server.MapPath( strPath & strFile)
     ' clear the buffer
     Response.Buffer = True
     Response.Clear

     ' create stream
     Set objStream = Server.CreateObject("ADODB.Stream")
     objStream.Open

     ' set as binary
     objStream.Type = 1

     ' check the file exists
     Set objFilesystem = Server.CreateObject("Scripting.FileSystemObject")
     if not objFilesystem.FileExists(strFilename) then
          Response.Write("<h1>Error</h1>: " & strFilename & " does not exist<p>")
          Response.End
     end if

     ' get length of file
     Set objFilestream = objFilesystem.GetFile( strFilename )
     intFilelength = objFilestream.size
 
     objStream.LoadFromFile( strFilename )
     if err then
          Response.Write("<h1>Error: </h1>" & err.Description & "<p>")
          Response.End
     end if
     
     'format strFileName
     if Len( Trim(strDownloadFilename) ) > 0 then
          strDownloadFilename = Trim( strDownloadFilename )
     else
          strDownloadFilename = objFilestream.name
     end if

     ' send the headers to the users browser
     Response.AddHeader "Content-Disposition", "attachment; filename=" & strDownloadFilename
     Response.AddHeader "Content-Length", intFilelength
     Response.Charset = "UTF-8"
     Response.ContentType = "application/octet-stream"

     ' output the file to the browser
     Response.BinaryWrite objStream.Read
     Response.Flush

     ' tidy up
     objFilestream.Close
     Set objFilestream = Nothing
End Function


fileName = server.mappath(request("file"))
tempFile=split(filename,"\")
' lets shorten the url of the file that goes in the db
dbFileName = tempFile(ubound(tempFile))

set conn=Server.CreateObject("ADODB.Connection")
set rs=Server.CreateObject("ADODB.Recordset")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("/_private/data/tracking.mdb")
rs.open "SELECT * FROM tracking WHERE download='  ' ",conn,2,2
rs.Addnew
rs("download")=dbFileName
rs("username")=session("fname") & " " & session("lname")
realdatetime= dateadd("h",-5,Now)
rs("date")=realdatetime
rs.update
rs.Close()
conn.Close()
set rs=nothing
set conn=nothing

Call downloadFile( Replace( dbFileName ,"/","\"),dbFileName,"somefolder/anotherfolder/" )
%>

************

Notice the line directly above, it has the path hardcoded. What's the best way to get around this - even if I create a separate download.asp for each folder so I can hard code it, I'm still left with the problem that the documents are another folder down - meaning there's over 50 of them:

somefolder1/anotherfolder1/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder1/anotherfolder2/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder1/anotherfolder3/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder1/anotherfolder4/- there are many docs, pdf's, ppt's, xls's etc in this folder

somefolder2/anotherfolder1/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder2/anotherfolder2/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder2/anotherfolder3/- there are many docs, pdf's, ppt's, xls's etc in this folder
somefolder2/anotherfolder4/- there are many docs, pdf's, ppt's, xls's etc in this folder

etc...

Any ideas?
0
Comment
Question by:seanpowell
  • 14
  • 6
  • 3
  • +2
26 Comments
 
LVL 29

Expert Comment

by:Göran Andersson
ID: 9650786
This code picks out just the file name from the parameter passed to the page:

fileName = server.mappath(request("file"))
tempFile=split(filename,"\")
' lets shorten the url of the file that goes in the db
dbFileName = tempFile(ubound(tempFile))

Do this instead, and you have the path also:

fileName = server.mappath(request("file"))
lngPos=InStrRev(fileName,"\")
dbFileName=Mid(fileName,lngPos+1)
strPath=Left(fileName,lngPos-1)

Now you can use it when getting the file:

Call downloadFile(dbFileName,dbFileName,strPath)
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9650857
I'm getting this when I make that change:

Server.MapPath() error 'ASP 0172 : 80004005'
Invalid Path
/manual/download.asp, line 9
The Path parameter for the MapPath method must be a virtual path. A physical path was used.
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9650975
You could define constants and declare the file path in download.asp
eg:
suploadpath="C:/webroot/upload/docs"

sdownloadpath=suploadpath & strPath

Cheers!!
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651055
I don't follow you there...
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9651143
Define the root download folder as a constant..say c:\downloads is your download folder.

get the folder name and file path from the query string.

eg:\doc\temp.pdf

Now you can get the actual file path by combining the two ..

eg:: c:\downloads\doc\temp.pdf

and use the following function..

Function downloadFile( strFile, strDownloadFilename, strPath )

    Dim strFilename,objStream,objFilesystem,objFilestream
    Dim intFileLength
    ' get path of specified file
    strFilename = strPath
     ' clear the buffer
    Response.Buffer = True
    Response.Clear

    ' create stream
    Set objStream = Server.CreateObject("ADODB.Stream")
    objStream.Open

    ' set as binary
    objStream.Type = 1

    ' check the file exists
    Set objFilesystem = Server.CreateObject("Scripting.FileSystemObject")
    if not objFilesystem.FileExists(strFilename) then
         Response.Write("<h1>Error</h1>: " & strFilename & " does not exist<p>")
         Response.End
    end if

    ' get length of file
    Set objFilestream = objFilesystem.GetFile( strFilename )
    intFilelength = objFilestream.size

     objStream.LoadFromFile( strFilename )
    if err then
         Response.Write("<h1>Error: </h1>" & err.Description & "<p>")
         Response.End
    end if
   
     'format strFileName
    if Len( Trim(strDownloadFilename) ) > 0 then
         strDownloadFilename = Trim( strDownloadFilename )
    else
         strDownloadFilename = objFilestream.name
    end if

    ' send the headers to the users browser
    Response.AddHeader "Content-Disposition", "attachment; filename=" & strDownloadFilename
    Response.AddHeader "Content-Length", intFilelength
    Response.Charset = "UTF-8"
    Response.ContentType = "application/octet-stream"

    ' output the file to the browser
    Response.BinaryWrite objStream.Read
    Response.Flush

    ' tidy up
    objFilestream.Close
    Set objFilestream = Nothing
End Function


fileName = server.mappath(request("file"))
tempFile=split(filename,"\")
' lets shorten the url of the file that goes in the db
dbFileName = tempFile(ubound(tempFile))

set conn=Server.CreateObject("ADODB.Connection")
set rs=Server.CreateObject("ADODB.Recordset")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("/_private/data/tracking.mdb")
rs.open "SELECT * FROM tracking WHERE download='  ' ",conn,2,2
rs.Addnew
rs("download")=dbFileName
rs("username")=session("fname") & " " & session("lname")
realdatetime= dateadd("h",-5,Now)
rs("date")=realdatetime
rs.update
rs.Close()
conn.Close()
set rs=nothing
set conn=nothing

CONST sDownload Path="C:\Downloads\"
' ** Use this if you are not passing the folder name along the querystring **
'strFolderPath="somefolder/anotherfolder/"  
strFullPath=sDownload & strFolderPath & request.querystring("file")
Call downloadFile( Replace( dbFileName ,"/","\"),dbFileName,strFullPath )


Cheers!!
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9651151
CONST sDownload Path="C:\Downloads\"

Should be

CONST sDownload="C:\Downloads\"

Cheers!!

0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651439
Sorry - I may be missing something:

CONST sDownload="C:\Downloads\"
' ** Use this if you are not passing the folder name along the querystring **
'strFolderPath="somefolder/anotherfolder/"  
strFullPath=sDownload & strFolderPath & request.querystring("file")
Call downloadFile( Replace( dbFileName ,"/","\"),dbFileName,strFullPath )

The only constants in the folder locations in the site are:

http://domain.com/folder/

So I would write your code like:
CONST sDownload="http://domain.com/folder/"

This:
'strFolderPath="somefolder/anotherfolder/"

if you look at my example above, could be:

'strFolderPath="somefolder1/anotherfolder1/"
'strFolderPath="somefolder2/anotherfolder5/"
'strFolderPath="somefolder3/anotherfolder23/"

etc.


So how would this work?
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9651547
>>http://domain.com/folder/
<%=server.mappath("folder")%> should give you your root downloads folder.

so,
CONST sDownload="http://domain.com/folder/" becomes..

CONST sDownload=server.mappath("folder")

This should get you the root folder. Now since you are passing the subfolder path along the query string,

your full file path would be..

strfullpath=sDownload & request.querystring("file")

Cheers!!
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651602
I think I follow you - however I get:

Microsoft VBScript compilation error '800a0415'

Expected literal constant

/manual/download_new.asp, line 80

CONST sDownload=server.mappath("manual")
----------------------------------------^

Do I need this somewhere:
<%=server.mappath("manual")%>
0
 
LVL 29

Expert Comment

by:Göran Andersson
ID: 9651672
That's right. The function uses a virtual path.

Change this:
strFilename = Server.MapPath( strPath & strFile)
to
strFilename = strPath & "\" & strFile
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651704
Actually I originally had this:
strFilename = Server.MapPath( strPath & strFile)

ap_sajith changed it to:
strFilename = strPath

So now I need to change it to:
strFilename = strPath & "\" & strFile

I'll give it a try...
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651712
No change...
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9651750
change CONST sDownload=server.mappath("manual")
to
dim sDownload
sDownload=server.mappath("manual")

cheers!!
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 31

Author Comment

by:seanpowell
ID: 9651767
That just gives me a blank page when I click onthe word Doc link...
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9651978
Here is the adjusted download.asp page incorporating all the modifications from above:


<%
response.buffer=true

Function downloadFile( strFile, strDownloadFilename, strPath )

    Dim strFilename,objStream,objFilesystem,objFilestream
    Dim intFileLength
    ' get path of specified file
    strFilename = strPath & "\" & strFile
     ' clear the buffer
    Response.Buffer = True
    Response.Clear

    ' create stream
    Set objStream = Server.CreateObject("ADODB.Stream")
    objStream.Open

    ' set as binary
    objStream.Type = 1

    ' check the file exists
    Set objFilesystem = Server.CreateObject("Scripting.FileSystemObject")
    if not objFilesystem.FileExists(strFilename) then
         Response.Write("<h1>Error</h1>: " & strFilename & " does not exist<p>")
         Response.End
    end if

    ' get length of file
    Set objFilestream = objFilesystem.GetFile( strFilename )
    intFilelength = objFilestream.size

     objStream.LoadFromFile( strFilename )
    if err then
         Response.Write("<h1>Error: </h1>" & err.Description & "<p>")
         Response.End
    end if
   
     'format strFileName
    if Len( Trim(strDownloadFilename) ) > 0 then
         strDownloadFilename = Trim( strDownloadFilename )
    else
         strDownloadFilename = objFilestream.name
    end if

    ' send the headers to the users browser
    Response.AddHeader "Content-Disposition", "attachment; filename=" & strDownloadFilename
    Response.AddHeader "Content-Length", intFilelength
    Response.Charset = "UTF-8"
    Response.ContentType = "application/octet-stream"

    ' output the file to the browser
    Response.BinaryWrite objStream.Read
    Response.Flush

    ' tidy up
    objFilestream.Close
    Set objFilestream = Nothing
End Function


fileName = server.mappath(request("file"))
tempFile=split(filename,"\")
dbFileName = tempFile(ubound(tempFile))

set conn=Server.CreateObject("ADODB.Connection")
set rs=Server.CreateObject("ADODB.Recordset")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("/_private/data/tracking.mdb")
rs.open "SELECT * FROM tracking WHERE download='  ' ",conn,2,2
rs.Addnew
rs("download")=dbFileName
rs("username")=session("fname") & " " & session("lname")
realdatetime= dateadd("h",-5,Now)
rs("date")=realdatetime
rs.update
rs.Close()
conn.Close()
set rs=nothing
set conn=nothing

dim sDownload
sDownload=server.mappath("manual")
strfullpath=sDownload & request.querystring("file")

%>
0
 
LVL 21

Expert Comment

by:ap_sajith
ID: 9652469
Try this..

<%
response.buffer=true

Function downloadFile( strFile, strDownloadFilename, strPath )

    Dim strFilename,objStream,objFilesystem,objFilestream
    Dim intFileLength
    ' get path of specified file
    strFilename = strPath & "\" & strFile
     ' clear the buffer
    Response.Buffer = True
    Response.Clear

    ' create stream
    Set objStream = Server.CreateObject("ADODB.Stream")
    objStream.Open

    ' set as binary
    objStream.Type = 1

    ' check the file exists
    Set objFilesystem = Server.CreateObject("Scripting.FileSystemObject")
    if not objFilesystem.FileExists(strFilename) then
         Response.Write("<h1>Error</h1>: " & strDownloadFileName & " does not exist<p>") ' ** DO NOT SHOW THE FULL PATH **
         Response.End
    end if

    ' get length of file
    Set objFilestream = objFilesystem.GetFile( strFilename )
    intFilelength = objFilestream.size

     objStream.LoadFromFile( strFilename )
    if err then
         Response.Write("<h1>Error: </h1>" & err.Description & "<p>")
         Response.End
    end if
   
     'format strFileName
    if Len( Trim(strDownloadFilename) ) > 0 then
         strDownloadFilename = Trim( strDownloadFilename )
    else
         strDownloadFilename = objFilestream.name
    end if

    ' send the headers to the users browser
    Response.AddHeader "Content-Disposition", "attachment; filename=" & strDownloadFilename
    Response.AddHeader "Content-Length", intFilelength
    Response.Charset = "UTF-8"
    Response.ContentType = "application/octet-stream"

    ' output the file to the browser
    Response.BinaryWrite objStream.Read
    Response.Flush

    ' tidy up
    objFilestream.Close
    Set objFilestream = Nothing
End Function


fileName = strDownloadFileName

set conn=Server.CreateObject("ADODB.Connection")
set rs=Server.CreateObject("ADODB.Recordset")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("/_private/data/tracking.mdb")
rs.open "SELECT * FROM tracking WHERE download='  ' ",conn,2,2
rs.Addnew
rs("download")=dbFileName
rs("username")=session("fname") & " " & session("lname")
realdatetime= dateadd("h",-5,Now)
rs("date")=realdatetime
rs.update
rs.Close()
conn.Close()
set rs=nothing
set conn=nothing

dim sDownload
strfullpath=server.mappath("manual")
sfile=Request.Querystring("file")
CALL downloadFile(sfile, mid(sfile,instrrev(str,"\")+1), strfullpath )
'SAMPLE STRINGS WOULD BE: strFile-"docs\folder2\test.doc" , strDownloadFilename-"test.doc",strPath-"C:\webroot\manual"
%>

Cheers!!
0
 
LVL 46

Accepted Solution

by:
fritz_the_blank earned 500 total points
ID: 9652821
I am coming to this late, but it seems to me the issue here is how to get the file name and the path from the request object. Then those two values could be passed to the function. How about something like this:

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
<TITLE></TITLE>
<SCRIPT LANGUAGE=vbscript>
sub findFileAndPath()
      'request.querystring("file") yields somefolder/anotherfolder/somedoc.doc
      strParameter = "somefolder/anotherfolder/somedoc.doc"
      strFile =  Right(strParameter,Len(strParameter)-instrrev(strParameter,"/"))
      strPath = Left(strParameter, Len(strParameter) - Len(strFile) )
      msgbox "Path: " & strPath & vbTab & "File: " & strFile
end sub
</SCRIPT>
</HEAD>
<BODY onLoad=findFileAndPath>
</BODY>
</HTML>


If this yields the necessary parameters, then we could do something like:


strParameter = request.querystring("file")
strFile =  Right(strParameter,Len(strParameter)-instrrev(strParameter,"/"))
strPath = Left(strParameter, Len(strParameter) - Len(strFile) )

Call downloadFile( strFile,strFile,strPath)


We should check to make sure, however, that the strPath isn't missing or adding an extra / somewhere.

Fritz the Blank
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653031
You nailed it Fritz.
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653059
This is perfect:

strParameter = request.querystring("file")
strFile =  Right(strParameter,Len(strParameter)-instrrev(strParameter,"/"))
strPath = Left(strParameter, Len(strParameter) - Len(strFile) )

Call downloadFile( strFile,strFile,strPath)

The links are now coded as:
<a href="../download.asp?file=somefolder/somefolder/somedoc.doc

What's written to the db is:
somedoc.doc

It would be nice if I had the other 2 "somefolder" names in the db along with the file - but it's not a deal breaker...
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 9653250
just do this:

rs("download")=request.("file")


FtB
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653331
:-(

Microsoft VBScript compilation error '800a03f2'

Expected identifier

/manual/download.asp, line 69

rs("download")=request.("file")
-----------------------^
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653339
I think its
rs("download")=request("file")
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653392
Yes, that did it.
I think I read somewhere that knowing when to remove a period automatically advances you to ASP "Wizard" level.
0
 
LVL 31

Author Comment

by:seanpowell
ID: 9653429
Thanks FtB

I've posted two other Q's for GreenGhost and ap_sajith. I hope that's okay... I really appreciate all your help and time.

Sean
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 9653457
Glad to have helped!

I see you posted points for GG and APS at:

http://www.experts-exchange.com/Web/Web_Languages/ASP/Q_20783497.html

http://www.experts-exchange.com/Web/Web_Languages/ASP/Q_20783499.html

Always a swell thing to do--I know that's what I always do.

FtB
0
 

Expert Comment

by:MRSONNY
ID: 10897758
why are the download limited to 20Mb
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Hello, all! I just recently started using Microsoft's IIS 7.5 within Windows 7, as I just downloaded and installed the 90 day trial of Windows 7. (Got to love Microsoft for allowing 90 days) The main reason for downloading and testing Windows 7 is t…
This demonstration started out as a follow up to some recently posted questions on the subject of logging in: http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_28634665.html and http://www.experts-exchange.com/Programming/…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

705 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now