Create temporary file and auto removed
I am writing a anti-leeching download script, and my plan is to create a temporary file, which is named by session ID, then after the session expires, the file will be automatically deleted. Is it possible ? And can you give me some tips how to do that in PHP ?
Thanks so muc开发者_StackOverflow中文版h for any reply
PHP has a function for that name tmpfile. It creates a temporary file and returns a resource. The resource can be used like any other resource.
E.g. the example from the manual:
<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>
The file is automatically removed when closed (using fclose()), or when the script ends. You can use any file functions on the resource. You can find these here. Hope this will help you?
Another solution would be to create the file in the regular way and use a cronjob to regular check if a session is expired. The expiration date and other session data could be stored in a database. Use the script to query that data and determine if a session is expired. If so, remove it physically from the disk. Make sure to run the script once an hour or so (depending on your timeout).
So we have one or more files available for download. Creating a temporary file for each download requests is not a good idea. Creating a symlink()
for each file instead is a much better idea. This will save loads of disk space and keep down the server load.
Naming the symlink after the user's session is a decent idea. A better idea is to generate a random symlink name & associate with the session, so the script can handle multiple downloads per session. You can use session_set_save_handler()
(link) and register a custom read
function that checks for expired sessions and removes symlinks when the session has expired.
Could you explain your problem a bit more deeply? Because I don't see a reason why not to use $_SESSION
. The data in $_SESSION
is stored server-side in a file (see http://php.net/session.save-path) BTW. At least by default. ;-)
Ok, so we have the following requirements so far
- Let the user download in his/her session only
- no copy & paste the link to somebody else
- Users have to download from the site, e.g. no hotlinking
- Control speed
Let's see. This is not working code, but it should work along these lines:
<?php // download.php
session_start(); // start or resume a session
// always sanitize user input
$fileId = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT);
$token = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW);
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL);
$script = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
// mush session_id and fileId into an access token
$secret = 'i can haz salt?';
$expectedToken = md5($secret . session_id() . $fileId);
// check if request came from download.php and has the valid access token
if(($expectedToken === $token) && ($referer === $script)) {
$file = realpath('path/to/files/' . $fileId . '.zip');
if(is_readable($file)) {
session_destroy(); // optional
header(/* stuff */);
fpassthru($file);
exit;
}
}
// if no file was sent, send the page with the download link.
?>
<html ...
<?php printf('a href="/download.php?fileId=%s&token=%s',
$fileId, $expectedToken); ?>
...
</html>
And that's it. No database required. This should cover requirements 1-3. You cannot control speed with PHP, but if you dont destroy the session after sending a file you could write a counter to the session and limit the number of files the user will be sent during a session.
I wholeheartedly agree that this could be solved much more elegantly than with this monkeyform hack, but as proof-of-concept, it should be sufficient.
I'd suggest you not to copy the file in the first place. I'd do the following: when user requests the file, you generate a random unique string to give him the link this way: dl.php?k=hd8DcjCjdCkk123
then put this string to a database, storing his IP address, maybe session and the time you've generated the link. Then another user request that file, make sure all the stuff (hash, ip and so on) matches and the link is not expired (e.g. not more that N hours have passed since the generation) and if everything is OK, use PHP to pipe the file. Set a cron job to look through the DB and remove the expired entries. What do you think?
tmpfile
Creates a temporary file with a unique name in read-write (w+) mode and returns a file handle. The file is automatically removed when closed (using fclose()), or when the script ends.
Maybe it's to late for answering but I'm try to share on feature googlize!
if you use CPanel there is a short and quick way for blocking external request on your hosted files which name is: HotLink.
you can Enable HotLinks on you Cpanel and be sure nobody can has request o your file from another hosting or use your files as a download reference.
To acheive this, I would make one file and protect it using chmod - making it unavailable to the public. Or, alternatively, save the contents in a database table row, fetch it whenever required.
Making it downloadable as a file. To do so, I would get the contents from the protected file, or if it is stored in a database table, fetch it and simply output it. Using php headers, I would, give it a desired name, extension, specify it's type, and finally force the browser to download the output as a solid file.
This way, you only need to save data in one place either, in a protected file or in database. Force client browser to download it as many times as the the conditions meet e.g., as long as the user is logged-in and so on. Without having to worry about the disk space, making any temp file, cronJobs and or auto-deletion of the file.
精彩评论