Solved

File Path as Parameter

Posted on 2003-10-30
26
622 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
[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
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Save ms data to server side. 19 64
Html fieldset fix its height and width 4 60
IIS components 2 66
Display if field is NOT "" or NOT null 6 37
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…
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/…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

751 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