|
Posted by Good Man on 05/14/07 17:58
"Zoe Brown" <zoenaomibrown@N-O-S-P-A-A-Mtesco.net> wrote in
news:Qzl1i.9904$H4.5066@newsfe2-gui.ntli.net:
>> Then, you have a file called "streamFile.php".... your user clicks on
>> the link "streamFile.php?key=3197fhduabsd", and your script looks up
>> the file according to the key, then uses readfile(); or a custom
>> function to stream the file to the browser....
>
> great, can you tell me a bit more about streaming the file to the
> browser, would this work for pdfs ? i presume this wont mean that
> they will abel to rightclick and download though ?
they still might be able to rightclick and download, though they won't get the real filename in that case (they will probably be prompted to download the file "streamFile.php?key=asdifoh" even though its a PDF).
yes, you can stream any type of file to the browser: http://ca.php.net/readfile is the PHP manual page, though if there is any chance your streamed files will be greater than 2MB, you should use the "readfile_chunked" function on that page (posted by chrisputnam at gmail dot com), it's a winner (ive used it on several sites).
> but isn't you approach just as risky as having the pdf file in the
> public domain with a random name.
not at all... because you are storing a random 'key' along with the filename, someone would have to guess the key. I tend to use 16-character keys. I am not worried in the slightest that someone will be able to guess a key like "6ruyhfn7k34bfdwq" and have it be valid. Obviously, your "streamFile.php" key should first check to make sure the key is valid (ie: it is in the database).
> Thanks for your input, I agree 100%. I thought that the .htaccess
> thing was the right way forward but am now reconsidering.
> Thanks again.
someone else suggested using PHP to control the .htaccess file. this is certainly possible, but again, with that scenario you will have two different types of access settings for a single website (if I recall correctly, your users are already logging in via a MySQL database). It's easier overall to keep a single type of access setting.
Sorry it took two days to respond, but I've been using my suggested method on a few different major websites for years, and it's easy / reliable.
In fact, here is my streamFile.php code, though I've removed some of my custom error functions and kept some custom SQL functions in. But you should get the point. Please excuse any word-wrapping:
-----
<?php
session_cache_limiter("must-revalidate");
session_start();
/*
*****************************************************************
* *
* Streaming a file to the user's browser: *
* *
*****************************************************************
*/
connectToDatabase(); //custom function
@$vFileKey = trim(mysql_real_escape_string($_REQUEST['vID']));
if ($vFileKey=="") { //no key?
echo "no such file.";
exit;
}
//pickup the file
$row = singlequery("SELECT FileName,FilePath FROM ProjectFiles WHERE FileKey='$vFileKey'"); //singlequery is a custom function
$vFilePath = $row['FilePath'];
$vFileName = $row['FileName'];
if($vFilePath=="") {
echo("There has been an error retrieving this file. Please call us and we will assist you.");
exit;
}
if(!is_file($vFilePath)) {
echo("We cannot deliver this file to you, as it is not on the server. Please call us and we will assist you.");
exit;
}
session_write_close(); //allows them to continue browsing the website and start other downloads while this one is going on
//now we stream the file, prompting a download
header("Cache-control: private");
// We'll be forcing the user to download it
header('Content-Type: application/octet-stream');
// It will be called whatever the file name is called, and given the attachment Disposition to force the download
header('Content-Disposition: attachment; filename="'.$vFileName.'"');
//this custom function is a good one for streaming files to browsers; it does not suffer from a 2MB limit like "readfile();" does
readfile_chunked($vFilePath);
//function used in this page (see above)
function readfile_chunked($filename,$retbytes=true) {
$chunksize = 1*(1024*1024); // how many bytes per chunk
$buffer = '';
$cnt =0;
// $handle = fopen($filename, 'rb');
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, $chunksize);
echo $buffer;
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
?>
Navigation:
[Reply to this message]
|