homepage Welcome to WebmasterWorld Guest from 23.20.63.27
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Hiding multiple download file links
issue in get.php?
brettxw




msg:4262101
 5:28 am on Feb 3, 2011 (gmt 0)

Hi guys, I searched all over the net and found myself on this forum with the answer(s). I am trying to hide the direct download links for my files, multiple files (about 10-20). I can do it with a single file by using the following code in my "get.php" file :

<?
$content_len=@filesize("file.zip");
Header("Content-type: application/zip");
Header("Content-type: octet-stream");
Header('Content-Disposition: attachment; filename="file.zip"');
if($content_len!=FALSE)
{
Header("Content-length: $content_len");
}
readfile("file.zip");
?>


That code works perfectly for a single file. Upon researching, I found the following code to use for multiple files :

<?

$id = $_GET['id'];

$filename = "/download/file_".$id.".zip";

header("Content-disposition: attachment; filename=".$filename."");

header('Content-type: application/octet-stream');

readfile($filename);

?>


And my download link would be get.php?id=1 or 2 or whatever number I am trying to download. The files are in the /download/ folder and named "file_1.zip". When I click the link to download this, it prompts me to save the zip file but the file name that appears is "/download/file_" as a ZIP, not the file I want it to download. Can anyone please help/assist me with this, I would greatly appreciate it!

Thank you guys!

 

coopster




msg:4262220
 2:00 pm on Feb 3, 2011 (gmt 0)

Welcome to WebmasterWorld, brettxw.

Your answer lies in the difference between the actual filename you need to read and push back to the user versus what you call it in the HTTP headers being sent back. Use the "real" file name in this line, perhaps setting a different variable or something ...
header("Content-disposition: attachment; filename=".$filename."");

Shingetsu




msg:4262293
 4:08 pm on Feb 3, 2011 (gmt 0)

What php version are you using?
By memory php 5.3 fast cgi
Demands that you put spaces around the dots so
Echo "1"."2" doesn't work, you need "1" . "2"

rocknbil




msg:4262359
 5:56 pm on Feb 3, 2011 (gmt 0)

but the file name that appears is "/download/file_" as a ZIP,


Do you mean the $id is not populated? Even if not, always check your input, and also check that the file exists. Second, when you use readfile, it's reading from the system, NOT a url. this

/download/file_".$id.".zip

would be looking for the download directory along side the system root, (like, /var in /var/www/home....) you won't have access.


if (isset($_GET['id']) and is_numeric($_GET['id']) and ($_GET['id'] > 0)) {
$id = $_GET['id'];
$filename = 'file_' . $id . '.zip';
$path = $_SERVER['DOCUMENT_ROOT'] . "/download/$filename";
if (is_file($path)) {
header("Content-disposition: attachment; filename=" . $filename);
header('Content-type: application/octet-stream');
readfile($path);
}
else { echo "<p>$filename is not a file!</p>"; }
}
else { echo "<p>Invalid file request.</p>"; }


Note also the removed quote after $filename in the header, empty string anyway, not needed.

If you're saying it's pointing to the wrong file, there are a number of ways to manage this. If it's all the same file - "file.zip" - and you just want to supply a different name for each user,


if (isset($_GET['id']) and is_numeric($_GET['id']) and ($_GET['id'] > 0)) {
$id = $_GET['id'];
$filename = 'file_' . $id . '.zip';
$file = 'file.zip';
$path = $_SERVER['DOCUMENT_ROOT'] . "/download/$file";
if (is_file($path)) {
header("Content-disposition: attachment; filename=" . $filename);
header('Content-type: application/octet-stream');
readfile($path);
}
else { echo "<p>$filename is not a file!</p>"; }
}
else { echo "<p>Invalid file request.</p>"; }


I'm not seeing where this comes in for "multiple files," but the choice is simple: store a filename and file association in a plain text or mysql database,

php-drama-part1.zip|1ff4dsfd.zip
php-drama-part2.zip|675fghdsfds.zip
php-drama-part3.zip|h6gndfg.zip

and wrap it in a for/foreach loop for each file.

foreach ($my_array as $key => $value) {
//
$filename = $key . '.zip';
$file = $value . '.zip';
//
}

brettxw




msg:4262473
 10:32 pm on Feb 3, 2011 (gmt 0)

Hey guys, thank you for getting back to me. I'm gonna try these out in about 10 minutes. Any problems I run into I'll be sure to screen cap what I see and the code I am using to help with my issues. Thank you again for the help. We'll see how it goes :)

brettxw




msg:4262503
 11:46 pm on Feb 3, 2011 (gmt 0)

if (isset($_GET['id']) and is_numeric($_GET['id']) and ($_GET['id'] > 0)) {
$id = $_GET['id'];
$filename = 'file_' . $id . '.zip';
$path = $_SERVER['DOCUMENT_ROOT'] . "/download/$filename";
if (is_file($path)) {
header("Content-disposition: attachment; filename=" . $filename);
header('Content-type: application/octet-stream');
readfile($path);
}
else { echo "<p>$filename is not a file!</p>"; }
}
else { echo "<p>Invalid file request.</p>"; }


Rock - That worked perfectly. I have a few more questions if you don't mind.

The idea I am trying to implement I have finally pieced the steps together. I am going to be providing my "VIP members" access to a VIP page where they can download the file from a faster server (hence why I want to hide the URLs). Now when I say multiple files, I mean that there will be about 10 files these VIP members will be able to download if they want. These files do not belong or interact with any other files, they are individual files. Rather then have every single file in that one /download file...Can I organize the files into their respective folders? ie) /files/os/9700/ (or whatever extension) All files that pertain to the 9700 will be in that folder and all files for say the 9800 would be in 'files/os/9800/' is that possible? if so it harder to do?

brettxw




msg:4262528
 12:50 am on Feb 4, 2011 (gmt 0)

Randomly thinking...Could I have a .get.php file in each folder and call to it that way?

brettxw




msg:4262635
 6:19 am on Feb 4, 2011 (gmt 0)

Another question...Now that I know how to create a time delay with a countdown visible, before the file link is visible and hide the direct file URL...Is there anyway I can set it up so the main link (image) to download the file opens a new window where the time delay will then start the countdown which then will start the download process on its own (where it prompts the person to save the file) Would that just entail editing the download image link code to create a popup and then having that popup be an .html file that has the PHP code to start the countdown delay and then force the download to start? If so, what is the code to use to start the force download? If not, then what would you recommend?


Also, not sure if this is against the rules of the forum (if it is I apologize and understand if the post needs to be edited to delete this portion) With that said, I was wondering if anyone would be interested in joining the team we have to run/maintain/code our site? I don't want to post the link up because I dont want to make it seem like I am trying to self promote or leech traffic. I assure you the site is not stupid (when it comes to the idea of the site) and is going to be VERY popular once we finish the coding for these new features. The last site I had created, became a huge and popular website when it came to BlackBerry devices. If anyone is interested, please, please let me know by PM or e-mail. brett@brettwyman.com

Thank you guys!

rocknbil




msg:4262882
 6:04 pm on Feb 4, 2011 (gmt 0)

Can I organize the files into their respective folders?


Sure. You'd have to figure out some way of automating it though. Via database, or some logic, you would wind up with an array

$dirs = Array (
'all_the_a_mpgs' => '/mpg/a',
'all_the_w_wmvs' => '/wmv/w'
);

Using the pseudo logic, you could name your files carefully and you wouldn't need an array, that is, if it's an mpg and starts with a, look for it in /mpg/a. So whatever you do, you'd replaces "/downloads" with "$variable"

$dir = $dirs['all_the_a_mpgs'];

or

$exts = array('mpeg','mpg','wmv','flv');
$first = substr($filename,0,1); // first letter
list ($f,$ext) = explode('.',$filename);
if (in_array($ext,$exts)) { $dir = "$exts/$first"; }
else { die("Unsupported file type"); }

$path = $_SERVER['DOCUMENT_ROOT'] . "/$dir/$filename";

Of course, if the directory is wrong it will die at your file name check, not because the file doesn't exist but because the path is invalid. So you could do a check for is_dir() first.

Is there anyway I can set it up so the main link (image) to download the file opens a new window...


<form action-"yourscript" target="_blank">

or

<form action-"yourscript" onsubmit="return newWin(this);">

where newWin is Javascript that opens a new window and processes form by reference, make sure it returns false to avoid submitting the form in the main window.

then having that popup be an .html


No, HTML has view source which will reveal your file paths. Using readfile() like you're doing is the way to do it, you can store them anywhere, even off the public html directory, and nevr reveal their location.

anyone would be interested in joining the team we have to run/maintain/code our site?


See commercial forum, but don't expect a lot of response to working on spec or venture. :-) Many here freelance and are paid, many have their own ventures that pay, but you can give it a try.

brettxw




msg:4262928
 8:40 pm on Feb 4, 2011 (gmt 0)

Thank you for the help, the help would def be paid.

In regards to the <form action code, the "yourscript" would be where I enter the javascript code for my countdown delay? And how do I or where do I input that code into the clickable image code?

brettxw




msg:4264059
 6:42 am on Feb 8, 2011 (gmt 0)

I wanted to make this thread active again as I am running into some confusion with the following :

Is there anyway I can set it up so the main link (image) to download the file opens a new window...


<form action-"yourscript" target="_blank">

or

<form action-"yourscript" onsubmit="return newWin(this);">



I have the following code on my site right now :

<a href="http://www.updateyourblackberry.com/php/gettour.php?id=5104"><img src="http://www.updateyourblackberry.com/images/buttons/dl1.png"></a>

What I want is that image, when clicked it will open a pop up window where I will have the Java/PHP for a timed countdown before making that file download begin or download link visible.

I appreciate all the help I've gotten from this website and the members. I've been on the site daily learning a lot of new things that I thought I would never be able to do! I love it! Thanks guys!

brettxw




msg:4269987
 6:14 am on Feb 21, 2011 (gmt 0)

Bringing this back to the top as I have another question in regards to this..Now that I set it up to hide the direct location of a file using the get.php script..How would I stop the direct linking of the php file then? example..After 20 second countdown, the link to download will be visible, which is :

http://www.example.com/php/get9780.php?id=6448

How can I make it so people can not just post that link for other people to start the download with out the 20 second countdown...Is there a way to set it up so after the countdown, the file will automatically start by opening the "save as" location box instead of the download link? This way the link wont be visible..

brettxw




msg:4270943
 8:36 am on Feb 23, 2011 (gmt 0)

Bringing this back to the top in the hopes for a solution.

rocknbil




msg:4271137
 5:31 pm on Feb 23, 2011 (gmt 0)

OK the first one I didn't understand. You're already opening the file and printing to STDOUT as an attachment. That hides the file.

How would I stop the direct linking of the php file then?


What you'd need to do is some sort of validation before supplying the file. Something like


- Validate user - how you'd do that would vary. If someone is, say, allowed a single download of a file, you could create a unique hash identifying them. Place the hash, expire time, and "downloaded" value in a database. When the record is created, you have

hash|file_id|downloaded|expires
fd546546fdguuufn5678|1234|0|2011-02-23-11:59:59

- Initiate the download, but first check that this user's download value is 0 and the expire date has not passed. If not, output error message. Using the stuff in previous posts, you locate the file by id and output.

- as soon as the download is initiated, you update the database. A better choice is to update the database when it completes, but how you do that reliably is kind of complex, hence the expire time. So
--- validate as above, if found and downloaded=0,
--- use ID to locate file
--- output download
--- update database setting downloaded to 1.

- If the previous should fail or time out, the expiration time will catch zombie records. You run a cron, hourly, daily, whatever, that does

update table set downloaded=1 where expires < now()

as a catch all to avoid zombie download records. Or better yet, if you don't want to check on old records and keep the DB small,

delete from where expires < now()

That's how I would start.

brettxw




msg:4275714
 3:35 am on Mar 3, 2011 (gmt 0)

Bringing this back up because I believe it is better suited here. I have found out EXACTLY how to do what I have been wanting to do since day 1! Just one problem...I am not sure how to implement these two and I know you guys will be able to assist me.

I have the following code for a countdown that will then make a link visible to click :

<script type="text/javascript">
document.write('<style type="text/css">#timed{display:none;}<\/style>')
function delay_link(){
var d=delay_link, t=document.getElementById('timed');
if(d.c&&d.c.nodeValue.replace(/[^\d]*/,'')-1>0){
d.c.nodeValue='\xa0\xa0'+(d.c.nodeValue.replace(/[^\d]*/,'')-1);
setTimeout('delay_link()', 1000)
return;
}
else if(!d.c){
d.c=document.createTextNode('35');
t.parentNode.insertBefore(d.c,t);
setTimeout('delay_link()', 1000)
return;
}
d.c.nodeValue='';
t.style.display='inline';
}
</script>

<div class="my_div"><id="timed" href='http://example.com/mylinkhere</a></div>
<script type="text/javascript">delay_link();</script>



Which works fine HOWEVER....How would I change that so I can have a form submit button to appear there..Or even text. I thought I would be able to post the form submit code :

<form name="contact_form" method="post" action="http://example.com/get.php?id=6480" onSubmit="return evalid()">
<input type="submit" name="Submit" value="Submit">
</form>


but I noticed that the countdown script above has <a id="timed" and I am not sure how to work that to remove the <a to get rid of the link code..

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved