Code based file download - php

Are there any good open, premade libraries or other systems for a file download based on unique codes distributed to the user?
The idea here is to generate a set of codes, that lets each user use his code to download a file. Preferably with a customizable limit to times downloaded and/or time limit.
if not, good ideas on how to implement this will be appreciated.

For generating those codes, you can use a function that generates a random string or simply the PHP's native rand() function. Then you create a table in the db that features the code you generated and the location of the file associated with it.
The download.php file should be called like this : download.php?hash=generated_code
And look like this:
<?php
// Retrieve filename and file location on the disk from the db
header('Content-disposition: attachment; filename='.$sql_response['filename']);
readfile($sql_response['filelocationondisk']);
?>
Also you can restrict download limits using cookies or counting the amount downloaded by IP in the database.

Related

limit number of times the file can be downloaded

I am creating a website , which people can create their own video and can download it from my server.
I want to limit the download count to 10.
So What I am planning is to serve a download file via a php file and update the count of the file to database.If it reaches 10 downloads.I deny the download.
But I guess it consume more resource.Is there any other way possible in linux server such as using htaccess or something like that ? So after a file is accessed 10 times it should be automatically deleted.
EDIT : its not users...any people can use this website for free.
If you don't want to avoid DB queries for this you can apply a simple technique in filename to indicate remaining limit Like filename-10, filename-9 etc. But to use this approach u need to update the part after "-" on each download.
This could be one approach.
I one of the simplest solution,
in the user profile folder store the file in the file system and when the counter in the database reaches 10 then use unlink() method in php to delete that file.

Saving a file generated by AJAX script

Good evening.
I am using Yii framework and mPDF library to generate some PDF files via Ajax script and I need to force "save as" dialogue in users' browsers.
I know how to solve this issue with a single user dowloading a single file.
Does anyone have a tip on how could I make it all work on high-load system (e.g. several users trying to generate and download a PDF will attempt to access one temp file which would cause an error)?
Should I generate a separate file for each session? And which way would be nice for cleaning these temp files?
Thank you for your help.
you should use tempnam http://www.php.net/manual/en/function.tempnam.php to generate the temp files. they'll be uniquely named, so it'll be easy to make one per session. Just delete as normal when you're done with them.
Make an invisible iframe. From JS set that iframe's src to the script on your server that generates the PDF.
<iframe src="http://yoursite.com/download-file.php?report=pdf&param1=value1&param2=value2..." width="1" height="1"></iframe>
Then (and I'm not sure how you do this with mPDF) the point is to output the file from script directly into the browser. It's something like this:
<?php
$x = some_function($_GET['param1'],$_GET['param2', ...); // PDF GEN. ROUTINE, BASED ON REQUEST DATA, HOWEVER YOU DO IT
header('Content-type: application/pdf');
echo $x;
That should solve all your concerns.
First of all, I'd recommend you to generate a different temp file for each generated PDF, in order to avoid any possible error like one user downloading somebody else's PDF, etc.
To clean up the temp directory, I'd use a cronjob that deletes all files older than N days.
In order to "force save dialog", you have to set the Content-disposition header to attachment:
header('Content-Disposition: attachment; filename="myfile.pdf"');

Download with different name

I'm setting up a script that'll download files from a URL with wget and make them available for download. I'd like to save them each with unique ID numbers, however the downloaded file must be called something different. How can I initiate a download of a file with a different name than is stored on the server?
Many thanks in advance.
You can use header
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile("/path/to/file");
You can also have a counter that counts the number of files you are downloading and after you download each one you can rename the file name to xxxx1.dat, then you'll have xxxx2.dat, etc.
That will also allow you to know the order of the files, if that is of some interest to you.

File uploads with php - displaying a list of files

I am in the middle of making a script to upload files via php. What I would like to know, is how to display the files already uploaded, and when clicking on them open them for download. Should I store the names and path in a database, or just list the conents of a directory with php?
Check out handling file uploads in PHP. A few points:
Ideally you want to allow the user to upload multiple files at the same time. Just create extra file inputs dynamically with Javascript for this;
When you get an upload, make sure you check that it is an upload with is_uploaded_file;
Use move_uploaded_file() to copy the file to wherever you're going to store it;
Don't rely on what the client tells you the MIME type is;
Sending them back to the client can be done trivially with a PHP script but you need to know the right MIME type;
Try and verify that what you get is what you expect (eg if it is a PDF file use a library to verify that it is), particularly if you use the file for anything or send it to anyone else; and
I would recommend you store the file name of the file from the client's computer and display that to them regardless of what you store it as. The user is just more likely to recognise this than anything else.
Storing paths in the database might be okay, depending on your specific application, but consider storing the filenames in the database and construct your paths to those files in PHP in a single place. That way, if you end up moving all uploaded files later, there is only one place in your code you need to change path generation, and you can avoid doing a large amount of data transformation on your "path" field in the database.
For example, for the file 1234.txt, you might store it in:
/your_web_directory/uploaded_files/1/2/3/1234.txt
You can use a configuration file or if you prefer, a global somewhere to define the path where your uploads are stored (/your web directory/uploaded files/) and then split characters from the filename (in the database) to figure out which subdirectory the file actually resides in.
As for displaying your files, you can simply load your list of files from the database and use a path-generating function to get download paths for each one based on their filenames. If you want to paginate the list of files, try using something like START 0, LIMIT 50; in mySQL. Just pass in a new start number with each successive page of upload results.
maybe you should use files, in this sense:
myfile.txt
My Uploaded File||my_upload_dir/my_uploaded_file.pdf
Other Uploaded File||my_upload_dir/other_uploaded.html
and go through them like this:
<?php
$file = "myfile.txt";
$lines = file($file);
$files = array();
for($i=0;$i<=count($lines)-1;$i++) {
$parts = explode($lines[$i]);
$name = parts[0];
$filename = parts[1];
$files[$i][0] = $name;
$files[$i][1] = $filename;
}
print_r($files);
?>
hope this helps. :)
What I always did (past tense, I haven't written an upload script for ages) is, I'd link up an upload script (any upload script) to a simple database.
This offers some advantages;
You do not offer your users direct insight to your file system (what if there is a leak in your 'browse'-script and you expose your whole harddrive?
You can store extra information and meta-data in an easy and efficient way
You can actually query for files / meta-data instead of just looping through all the files
You can enable a 'safe-delete', where you delete the row, but keep the file (for example)
You can enable logging way more easily
Showing files in pages is easier
You can 'mask' files. Using a database enables you to store a 'masked' filename, and a 'real' filename.
Obviously, there are some disadvantages as well;
It is a little harder to migrate, since your file system and database have to be in sync
If an operation fails (on one of both ends) you have either a 'corrupt' database or file system
As mentioned before (but we can not mention enough, I'm afraid); _Keep your uploading safe!_
The MIME type / extension issue is one that is going on for ages.. I think most of the web is solid nowadays, but there used to be a time when developers would check either MIME type or extension, but never both (why bother?). This resulted in websites being very, very leaky.
If not written properly, upload scripts are big hole in your security. A great example of that is a website I 'hacked' a while back (on their request, of course). They supported the upload of images to a photoalbum, but they only checked on file extension. So I uploaded a GIF, with a directory scanner inside. This allowed me to scan through their whole system (since it wasn't a dedicated server; I could see a little more then that).
Hope I helped ;)

How do I track file downloads

I have a website that plays mp3s in a flash player. If a user clicks 'play' the flash player automatically downloads an mp3 and starts playing it.
Is there an easy way to track how many times a particular song clip (or any binary file) has been downloaded?
Is the play link a link to the actual
mp3 file or to some javascript code
that pops up a player?
If the latter, you can easily add your
own logging code in there to track the
number of hits to it.
If the former, you'll need something
that can track the web server log
itself and make that distinction. My
hosting plan comes with Webalizer,
which does this nicely.
It's a javascript code so that answers that.
However, it would be nice to know how to track downloads using the other method (without switching hosts).
The funny thing is I wrote a php media gallery for all my musics 2 days ago. I had a similar problem. I'm using http://musicplayer.sourceforge.net/ for the player. And the playlist is built via php. All music requests go to a script called xfer.php?file=WHATEVER
$filename = base64_url_decode($_REQUEST['file']);
header("Cache-Control: public");
header('Content-disposition: attachment; filename='.basename($filename));
header("Content-Transfer-Encoding: binary");
header('Content-Length: '. filesize($filename));
// Put either file counting code here, either a db or static files
//
readfile($filename); //and spit the user the file
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_,', '+/='));
}
And when you call files use something like:
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_,');
}
http://us.php.net/manual/en/function.base64-encode.php
If you are using some JavaScript or a flash player (JW player for example) that requires the actual link of an mp3 file or whatever, you can append the text "&type=.mp3" so the final link becomes something like:
"www.example.com/xfer.php?file=34842ffjfjxfh&type=.mp3". That way it looks like it ends with an mp3 extension without affecting the file link.
Use your httpd log files. Install http://awstats.sourceforge.net/
Use bash:
grep mp3 /var/log/httpd/access_log | wc
If your song / binary file was served by apache, you can easily grep the access_log to find out the number of downloads. A simple post-logrotate script can grep the logs and maintain your count statistics in a db.
This has the performance advantage by not being in your live request code path. Doing non-critical things like stats offline is a good idea to scale your website to large number of users.
You could even set up an Apache .htaccess directive that converts *.mp3 requests into the querystring dubayou is working with. It might be an elegant way to keep the direct request and still be able to slipstream log function into the response.
Is the play link a link to the actual mp3 file or to some javascript code that pops up a player?
If the latter, you can easily add your own logging code in there to track the number of hits to it.
If the former, you'll need something that can track the web server log itself and make that distinction. My hosting plan comes with webalizer, which does this nicely.
Is there a database for your music library? If there is any server code that runs when downloading the mp3 then you can add extra code there to increment the play count. You could also have javascript make a second request to increment the play count, but this could lead to people/robots falsely incrementing counts.
I used to work for an internet-radio site and we used separate tables to track the time every song was played. Our streams were powered by a perl script running icecast, so we triggered a database request every time a new track started playing. Then to compute the play count we would run a query to count how many times a song's id was in the play log.
The problem I had with things like AWStats / reading through web server logs is that large downloads can often be split in data chunks within the logs. This makes reconciling the exact number of downloads quite hard.
I'd suggest the Google Analytics Event Tracking, as this will register once per click on a download link.

Categories