I have a direct link to a file I want to give out to my visitors, for example:
http://www.mydomain.com/mynewmix.mp3
Is there any way I can run the following query when the link above is being ping/hit/downloaded?
UPDATE `db` SET `downloaded`=`downloaded`+1 WHERE `url`='http://www.mydomain.com/mynewmix.mp3'
Any kind of help I can get on this is greatly appreciated. Thank you so much in advance.
Yes this is possible. you can use rewrite module in apache. so you can say that for all (mp3) files the server shouldn't return the mp3 file but instead run a php file/script which executes your query and returns the mp3 file.
this might help you: http://www.workingwith.me.uk/articles/scripting/mod_rewrite
in your .htaccess file:
RewriteEngine on
RewriteRule ^\.mp3$ index.php [L]
this will send all links ending with .mp3 to index.php (actualy it will still be the same link but the index.php will be executed)
other option you have:
RewriteRule ^.*/(\w)*\.mp3$ index.php?filename=$1 [L]
this will execute index.php with the GET veriable filename with the filename
eg. $_GET['filename'] = "filename" (when file: filename.mp3)
in index.php to let the user download the mp3 file (see: Can I serve MP3 files with PHP?):
header("Content-Transfer-Encoding: binary");
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
header('Content-length: ' . filesize("[file location eg: /home/files/sometrack.mp3]"));
header('Content-Disposition: attachment; filename="sometrack.mp3"');
header('X-Pad: avoid browser bug');
header('Cache-Control: no-cache');
readfile("[file location eg: /home/files/sometrack.mp3]");
exit();
you could do this dynamicly with the following code:
$fileName = $_GET['filename']."mp3"; //we stripped .mp3 in the apache rewrite (might not be so smart)
$fileLocation = "/your/location/".$filename;
header("Content-Transfer-Encoding: binary");
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
header('Content-length: ' . filesize($fileLocation));
header('Content-Disposition: attachment; filename="'.$fileName.'"');
header('X-Pad: avoid browser bug');
header('Cache-Control: no-cache');
readfile($fileLocation);
exit();
you can access the requested link with:
$_SERVER['REQUEST_URI'];
or the new (generated url with):
$_SERVER['REDIRECT_URL'];
I think there is another way that does what you want:
Create a new php file "download" to start download with parameters
Contents look like this (date and time are keys to get my mp3-file):
<?php
if (isset($_GET['date']) && is_string($_GET['date']) && isset($_GET['time']) && is_string($_GET['time']))
{
require_once($_SERVER['DOCUMENT_ROOT'] . "/bin/functions.php");
DownloadFile($_GET['date'],$_GET['time']);
}
?>
Create a different php file "functions.php" with the function "DownloadFile":
function DownloadFile($Date,$Time)
{
require('connection.php');
mysql_select_db($database, $instance);
$qry = "
UPDATE `table`
SET `Field1` = `Field1` + 1
WHERE `Field2` = '$Date' AND `Field3` = '$Time'
";
$result = mysql_query($qry, $instance) or die(mysql_error());
header('Content-type: Application/mp3');
header("Content-Length: " .(string)(filesize($file)));
header('Content-Disposition: attachment; filename=' . $file);
readfile($file);
}
Use different url for downloading (no anchor)
http://www.yoursite.com/xxx/download.php?date=2000-01-01&time=12:00:00
Yes you can do this. on click of url need to call ajax to run update query on success you proceed to download the file.
Related
File links are all http://website.com/f/xxx.png/zip/txt and so on.
I need to set it up so that if a user downloads that file it would download with a different name.
I have seen how to do this on a normal page, but I have no clue how making it work when the image itself is linked to is done.
Appreciate any help :)
Edit: Using the rewrite Steven Jeffries posted,
header('Content-Disposition: inline; filename=' . $originalFileName . "'");
header("Content-Type:" . $mimeType);
$im = imagecreatefrompng($filePathOnServer);
imagepng($im);
to display images and
header('Content-Disposition: attachment; filename=' . $originalFileName . "'");
header("Content-Type:" . $mimeType);
to make other files download solved the issues I had.
I think an easy way to do this would be to redirect download links to another script that handles what to download, etc. Basically, I'd set up a download dir, add some rewrite rules, and then create a script to handle what gets output.
Something like this (untested):
/path-to-web-root/download/.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.* /downloads/handle-downloads.php
/path-to-web-root/download/handle-downloads.php
$url = trim($_SERVER['REQUEST_URI'], '/');
if (preg_match('^#downloads/(?<real_filename>.*?)/(?<options>.*)/(?<fake_filename>.*)$#', $url, $matches)) {
// Double check my regex, but basically pull the real filename from the url here
$actual_file = "/path-to-webroot/f/{$matches['real_filename']}";
$options = explode('/', $matches['options']);
if (in_array('zip', $options)) {
// Handle zip, etc.
}
$fake_filename = $matches['fake_filename'];
if (file_exists($actual_file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($fake_filename).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($actual_file));
readfile($file);
exit;
}
}
Then, instead of having the download link being website.com/f/xxx.png/zip/txt, you could instead do website.com/download/xxx.png/zip/txt/new-filename.png. This would allow you to set the filename to whatever you wanted since the browser will just take what's at the end of the url.
Edit: I've included the relevant code from readfile's manual page.
You can set the file response file name by setting header parameter.
For example:
<?php
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="xyz.png"');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
...
More on PHP header function here: http://php.net/manual/en/function.header.php
This php file is supposed to:
receive a piece of information from a form on a different page
use this information to create an array of file paths to add to a zip file
create a dynamically named zip file using a class that's included.
force the download of the newly created zip file
numbers 1-3 are working flawlessly.
The page even forces the download of a zip file that is correctly named and is the right size, but when I try to open it, it says the file is invalid. I've seen similar problems in searches, but I have yet to find a solution.
If i enter the direct URL for the newly created zip into the browser, the file downloads and opens perfectly. As a matter of fact, my temporary fix was creating a dynamic direct link to the files :/
I should probably mention that this is hosted on the go daddy economy plan.
<?php
error_reporting(0);
include "gavScripts/connect_to_mysql.php";
require_once 'Zipper.php';
// prepare the file paths to add to the zip file and find the job/client name (for naming the zip folder)
if(isset($_POST['jobName']))
{
$clientID = $_POST['jobName'];
$clientSQL = mysql_query("SELECT clientName FROM job_client WHERE clientID = $clientID");
while($clientRow = mysql_fetch_array($clientSQL))
{
$clientName = $clientRow['clientName'];
}
$zipSQL = mysql_query("SELECT filePath FROM job_expense WHERE clientID = $clientID");
While($zipRow = mysql_fetch_array($zipSQL))
{
$filePaths[] = $zipRow['filePath'];
}
}
//create the zip folder and store the requested files
$zipper = new Zipper();
$zipper->add($filePaths);
$zipper->store('invoices/' . $clientName . '_Invoices.zip');
//download the zip
$fileDownload = 'invoices/' . $clientName . '_Invoices.zip';
$fileName = basename($fileDownload);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . $fileName . "");
header("Content-Length: " . filesize($fileDownload));
readfile($fileDownload);
?>
You may have trailing whitespace at the end of your script which is breaking your zip file. Is there a \r or \n (or both) after the closing ?>? Try removing the closing ?> which is optional anyway.
Try the following:
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime($fileName)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($fileName));
header('Connection: close');
readfile($fileName);
exit();
Might help.
I have a problem with counting downloads of file. There will be no problem if a link to the download file would look like this: http:// your.site.domain/download.php?file=filename.exe&customer=ABC_423. However my customer want to count statistics from link like this: http:// your.site.domain/downloadsfolder/ABC_423/filename.exe and also he needs to hotlink that link on other sites.
I think there would be solution in .htaccess file, but I don't know how to make a proper redirect.
My PHP script looks like this:
session_start();
define('SERVER_NAME', 'www.siteaddress.domain');
define('DOWNLOAD_PATH', 'http:// siteaddress.domain/versions/download');
define('DOWNLOAD_FILE', 'Setup.exe');
$filename = DOWNLOAD_PATH . '/' . $_GET['customer'] . '/' . DOWNLOAD_FILE;
$headers = get_headers($filename);
if ($headers[0] == 'HTTP/1.1 200 OK'){
// file exists, begin download procedure
if(isset($_GET['customer'])){
// begin update statistics
// mysql query to update specified row
}
// headers for downloading file
header("Content-Type: application/force-download");
header('Content-Type: application/x-unknown');
header("Content-Type: application/octet-stream");
//header("Content-Type: application/download"); // not sure if needed
header("Content-Disposition: attachment; filename=".basename($filename).";");
header("Accept-Ranges: bytes");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".remote_filesize(SERVER_NAME, $filename));
ob_clean();
flush();
readfile($filename);
exit;
}else{
echo 'File not found';
exit;
}
This is a simple RewriteRule in .htaccess. Something like this:
RewriteEngine On
RewriteRule ^/downloadsfolder/(.*)/(.*) /download.php?file=$2&customer=$1 [L]
Observe how a random char sequence is detected with (.*) and then used with $1 and $2 for each detected item in the translated URL.
Hope that helped!
I have script below for downloading files from a folder using PHP, it is working local but online it is reading and printing on the page instate of downloading.
if( $result && count($result) > 0){
$row = $result[0];
$book = true;
$Location = './files/';
$bookLocation = $Location . $row['file_name']; // exampe: report.zip
if( file_exists( $bookLocation ) ){
$fileLocation = $bookLocation;
$file_size = filesize($fileLocation);
echo 'Please wait downloading the file....';
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename=' . $row['file_name']);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $file_size);
ob_clean();
flush();
readfile($fileLocation);
exit;
}else{
echo '<h3>Sorry!, file not found...</h3>';
}
}
.htaccess script
RewriteEngine on
RewriteRule ^$ index.html
RewriteRule ^index.html$ index.php
RewriteRule ^([0-9]{1,9})(/)([^/\.]+[^/\.]+)(_+[^/\.]+)(\.html|)/?$ index.php?id=$1&cat=$3
RewriteRule ^([^/\.]+[^/\.]+)(\.html|)/?$ index.php?page=$1
RewriteRule ^(.*)(/)([0-9]{1,9})(/)(.*)(\.html|)/?$ index.php?view_file=$3&file=$5
RewriteRule ^(.*)(/)([0-9]{1,9})(/)(.*)(\.htm)/?$ index.php?download=$3
RewriteRule ^(author)(/)(.*)(.html)/?$ index.php?user=$1
Thanks for the help.
It is possible that in certain browsers, you set it to automatically download and run that particular file type.
If that is the case, there is no way to "fix" this. The browser decides what to do with the file, even if you tell it to download it, the user might have told it to run directly.
Big Edit
While my earlier comment is correct, you have a major issue in your code:
$file_size = filesize($fileLocation);
echo 'Please wait downloading the file....';
header('Content-Description: File Transfer');
You must remove that echo statement. It is bound to cause issues, such as the headers not being sent. Considering your description, I'd say this is your problem.
See, once you send any content, you cannot send more headers.
As Christian suggested, you must remove the echo statement in your code. If it doesn't work for you even after that, try replacing the line
header('Content-Type: application/force-download');
with
header('Content-Type: application/octet-stream');
I have a page with mp3s that are playable from a player, and there are also links to download the songs. When the user clicks on the download link, it needs to open the download dialog instead of opening a media player, so it was recommended to me to use this header script:
includes/auto-download.php:
<?php
$path = $_GET['path'];
header('Content-Disposition: attachment; filename=' . basename($path));
readfile($path);
?>
And then on my main page, the link looks like this:
Song Name
I seem to be doing something wrong with my paths, as when I click the link, the download box opens, and I can download a file with the correct name, but it doesn't contain any information.
To elaborate on my file structure, I've got this:
/Patrons (where my main index.php page is with my link
/Patrons/includes (where my auto-download.php script is)
/Patrons/Media/Audio/Date/ (this is where all the songs are)
Any help would be greatly appreciated!
Either change HTML code to this:
Song Name
OR change PHP code to this:
readfile('../'.$path);
$path needs to be the relative path to the file from the web root. with no leading slash. If the files are outside the web root you should use a fullpath (/home/webuser/song_files/song.mp3).
For example $path = 'song_files/'. $_GET['name_of_the_file'];
You should also check if the file does not exist and exit with an error.
Here is an example I made in codeigniter.
function _begin_download($document_data) {
basepath = 'uploads/';
$filepath = basepath . $document_data->filename;
if (file_exists($filepath)) {
header("Content-type: " . $document_data->mimetype);
header("Content-length: " . filesize($filepath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-disposition: attachment; filename="' . $document_data->filename . '"');
readfile($filepath);
exit();
} else {
exit('File not found.');
}
}