Solved

File Path as Parameter

Posted on 2003-10-30
26
613 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
ScreenConnect 6.0 Free Trial

Check out the updates in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI that improves session organization and overall user experience. See the enhancements for yourself!

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

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

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

Suggested Solutions

I would like to start this tip/trick by saying Thank You, to all who said that this could not be done, as it forced me to make sure that it could be accomplished. :) To start, I want to make sure everyone understands the importance of utilizing p…
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…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

770 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