X-Sendfile notification after finish download - php

I would need to set the download status to 0 when download has finished. I am using x-sendfile, but after finish download, dont set status.
My code:
header("X-Sendfile: $file");
header("Content-type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . $name . '"');
mysql_query("UPDATE `downloads` SET `download_status` = '1' WHERE `id` = '" . $last_down . "'");
Thanks for help

You can't detect when the client finished downloading the file if you using X-Sendfile.
Simplest way is stream file by script.
$handle = fopen($filepath, 'rb');
if ($handle !== false) {
#flock($handle, LOCK_SH);
$size = filesize($filepath);
$filename = basename($filepath);
$old_max_execution_time = ini_get('max_execution_time');
ini_set('max_execution_time', 0);
$old_cache_limiter = session_cache_limiter();
session_cache_limiter(false);
if (ob_get_length()) ob_clean();
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-disposition: attachment; filename="'. $filename .'"');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Accept-Ranges: bytes');
header('Cache-control: private');
header('Pragma: private');
set_time_limit(0);
while (! feof($handle) && (connection_status() === 0)) {
if (! $buffer = #fread($handle, $interval)) {
// Error
exit;
}
print($buffer);
flush();
}
#flock($handle, LOCK_UN);
#fclose($handle);
ini_set('max_execution_time', $old_max_execution_time);
session_cache_limiter($old_cache_limiter);
// ----------------------------------------------------
// Downloading complete!
// Here you can update your table row in DB...
// ----------------------------------------------------
exit;
}

Related

Adding another URL into a download script

I have a video streaming website which also allows users to download videos. This runs over a download script that loads the videos id on the server and initiates a direct file transfer.
Now I want to put another URL in front of it instead of having the direct file transfer. I tried to make a mod_rewrite rule, but it causes a loop and redirects on that URL forever. Its a link shortening service which allows monetarization.
So, how do I archieve this? Is it possible to archieve it with a mod_rewrite rule?
Trying the mod_rewrite rule, realizing I can't change the base_url variable in PHP because it would not find the file anymore.
$vid = intval($_GET['id']);
$label = intval($_GET['label']);
$sql = "SELECT * FROM video WHERE VID = ".$vid." LIMIT 1";
$rs = $conn->execute($sql);
$formats = $rs->fields['formats'];
$server = $rs->fields['server'];
$formats_arr = explode(',', $formats);
if ($server != '') {
$sql = "SELECT * FROM video v, servers s WHERE v.VID = ".$vid." AND v.server = s.video_url LIMIT 1";
$rs = $conn->execute($sql);
$video_root = $rs->fields['video_url'];
}
if (!$video_root) {
$video_root = $config['BASE_DIR']."/media/videos";
}
foreach ($formats_arr as $format) {
$f = explode('.', $format);
if ($label == $f[1]) {
if ($f[0] >= 481) {
$condition = $new_permisions['hd_downloads'];
} else {
$condition = $new_permisions['sd_downloads'];
}
$file = $video_root.'/h264/'.$vid.'_'.$f[1].'.'.$f[2];
$file_name = $vid.'_'.$f[1].'.'.$f[2];
break;
}
}
if ($condition == 1) {
ini_set('memory_limit', '-1');
if (!$server) {
if (file_exists($file) && is_file($file) && is_readable($file)) {
$conn->execute("UPDATE video SET download_num = download_num+1 WHERE VID = ".$vid." LIMIT 1");
#ob_end_clean();
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
header('Cache-control: private');
header('Pragma: private');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-Length: ' .filesize($file));
readfile($file);
exit();
} else {
VRedirect::go($config['BASE_URL']. '/error');
}
} else {
$conn->execute("UPDATE video SET download_num = download_num+1 WHERE VID = ".$vid." LIMIT 1");
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
$stream = fopen('php://output', 'w');
$ch = curl_init($file);
curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $fd, $length) use ($stream) {
return fwrite($stream, fread($fd, $length));
});
The download button should open URL/download.php with my link shortener URL in front of it, so it will load and redirect to the file download URL.

How do I know how many times my file has really downloaded?

The task is to create a controller to count the number of file downloads. It also must be able to account for failed or cancelled downloads. I was wondering if anyone knew the best way to go about accomplishing this.
$file = $_GET['download'];
if (ob_get_level()) {
ob_end_clean();
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
return filesize($file);`
$size = filesize($file);
Then if the number of bytes given is approximately equal to the file size:
if ( $size < given bytes) {
$handle = fopen("counter.txt", "r");
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$buffer=$buffer+1;
}
fclose($handle);
$fp = fopen("counter.txt", "w");
$test = fwrite( $fp, $buffer);
fclose($fp);
}
How to know the number of bytes sent by server to the user after clicking on link?
I'll start with what should be comments:
You've tagged this as javascript, but your quesiotn appears to have nothing to do with javascript. Please don't do that.
I assume you are aware of the gaping security hole exposed by your script / that you are not concerned about it.
Your handling of output buffering is wrong.
return filesize($file);
What is this line of code supposed to do?
header('Expires: 0');
no.
header('Pragma: public');
again, no.
As to your question - its all covered in the manual:
<?php
ignore_user_abort(1);
$file = $_GET['download'];
if (!is_readable($file)) {
die "No such file";
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: max-age=0; must-revalidate');
header('Content-Length: ' . filesize($file));
$count=0;
$ih=fopen($file, 'r');
while (CONNECTION_NORMAL==connection_status() && !feof($ih)) {
print fgets($ih, 4096);
}
log_completion(feof($ih));
BTW: This does not give an accurate record if the file was downloaded - you can only tell if the content has left PHP land.

How to properly send file to browser?

I want to send a file directly to browser:
<?php
#ini_set('error_reporting', 0);
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 'Off');
#ob_implicit_flush();
$file = 'ORG.iso';
$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$file_size = filesize($file);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $quoted);
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $file_size);
#ob_end_flush();
set_time_limit(0);
$f = fopen($file, 'r');
while (!feof($f))
{
$buff = fread($f, 204800);
echo $buff;
sleep(1);
}
fclose($f);
It shows correct file size in Firefox and Chrome right after visitor enters the link. However it does not work in jDownloader. It seems like jDownloader is waiting for the whole script to end.
When I try a normal, static file from the same webserver- jDownloader shows file size instantly.
So obviously something is wrong with my script.

Youtube downloader script on server end

I am trying to generate a script which can download youtube videos on the server, I would like the user to provide the video url.
I have searched a lot but, could not make it work. Here's my code.
<?php
// Check download token
if (empty($_GET['mime']) OR empty($_GET['token']))
{
exit('Invalid download token 8{');
}
// Set operation params
$mime = filter_var($_GET['mime']);
$ext = str_replace(array('/', 'x-'), '', strstr($mime, '/'));
$url = base64_decode(filter_var($_GET['token']));
$name = urldecode($_GET['title']). '.' .$ext;
// Fetch and serve
if ($url)
{
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
{/*
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
*/}
else
{/*
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
*/}
$download_video_file = file_put_contents($file_path, fopen($url, 'r'));
exit;
}
// Not found
exit('File not found 8{');
?>
But I am still stuck at this, Please help me out.
You will get the code from here
Ref : https://code.google.com/p/php-youtube-downloader/
<?php
require_once('youtube.lib.php');
$download_link = get_youtube('http://www.youtube.com/watch?v=SAQZ0BDXn48');
// we will have array here, index 0 is the video ID and index 1 is the download link.
echo $download_link[1];
?>
http://php-youtube-downloader.googlecode.com/files/youtube_downloader.zip
GitHub : https://github.com/jeckman/YouTube-Downloader

Download YouTube video in server

I have created a YouTube search engine + download + MP3 convert script. I have used Jeckman's YouTube Downloader for creating this script. Everything is OK, except, I want to download the video into the server instead it downloading it to my computer. I want to do this because, after it gets download, I shall convert the video to MP3 using FFmpeg.
Is there any way to get the video downloaded in my server instead of my computer?
The download.php contains the following code:
<?php
// Check download token
if (empty($_GET['mime']) OR empty($_GET['token']))
{
exit('Invalid download token 8{');
}
// Set operation params
$mime = filter_var($_GET['mime']);
$ext = str_replace(array('/', 'x-'), '', strstr($mime, '/'));
$url = base64_decode(filter_var($_GET['token']));
$name = urldecode($_GET['title']). '.' .$ext;
// Fetch and serve
if ($url)
{
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
{
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
}
else
{
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
}
readfile($url);
exit;
}
// Not found
exit('File not found 8{');
?>
I've found out a solution to store the YouTube file to server. I have removed the header stuff and put $download_video_file = file_put_contents($file_path, fopen($url, 'r')); in place of readfile($url); and it worked like a magic! ^_^
Here's the complete code:
<?php
// Check download token
if (empty($_GET['mime']) OR empty($_GET['token']))
{
exit('Invalid download token 8{');
}
// Set operation params
$mime = filter_var($_GET['mime']);
$ext = str_replace(array('/', 'x-'), '', strstr($mime, '/'));
$url = base64_decode(filter_var($_GET['token']));
$name = urldecode($_GET['title']). '.' .$ext;
// Fetch and serve
if ($url)
{
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
{/*
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
*/}
else
{/*
header('Content-Type: "' . $mime . '"');
header('Content-Disposition: attachment; filename="' . $name . '"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
*/}
$download_video_file = file_put_contents($file_path, fopen($url, 'r'));
exit;
}
// Not found
exit('File not found 8{');
?>

Categories