sudden database disconnection in following code - php

I am recording the time at which the user downloaded a specific file using the following code. However, in this code, initially the download time is coming but later it's disconnecting the data base connection between client and server. If I remove the 'exit' (as shown), everything is coming fine but the downloaded file can be corrupted or damaged.
Can anyone check this code and explain what is wrong with it? I think the problem is with the exit, but what can I use instead of exit?
<?php
$f_name = $_POST["fn"];
$file = "../mt/sites/default/files/ourfiles/$f_name";
if (file_exists($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('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
//ob_clean();
// flush();
readfile($file);
// exit;
}
$con = mysql_connect("localhost","mt","mt");
if (!$con) {
die('Could not connect: ' . mysql_error());
} else {
echo "Connected";
}
// Create table
mysql_select_db("mt", $con);
mysql_query("INSERT INTO down_time (FileName,DateTime)
VALUES ('".$f_name."',NOW())");
mysql_close($con);
?>

If that happens on large files and/or slow connections, try to tweak max_execution_time in php.ini or from script using ini_set function.

well if you include the exit, your code just doesn't come to the point where it should insert the filename into db.
if you don't include the exit, you send the file contents and append "Connected" to it so the file has to be corrupted.
maybe you can try ob_start and ob_end_clean around your db stuff: http://php.net/manual/en/function.ob-start.php
this prevents anything from being sent to the output, so you don't have to use exit but nothing gets sent to the output after your file so it doesn't get corrupted
something like:
readfile($file);
}
ob_start();
$con = mysql_connect("localhost","mt","mt");
//all the DB stuff
mysql_close($con);
ob_end_clean();
?>
you can include exit after the ob_end_clean() just to be sure but this should work just fine.

Try:
<?php
$f_name = $_POST["fn"];
$file = "../mt/sites/default/files/ourfiles/$f_name";
if (!file_exists($file)) { die('File not found'); }
if (!$con = mysql_connect("localhost","mt","mt")) { die(mysql_error()); }
if (!mysql_select_db("mt")) { die(mysql_error()); }
$q = "INSERT INTO `down_time` (`FileName`, `DateTime`) VALUES ('"
. mysql_real_escape_string($f_name) . "',NOW())";
if (!mysql_query($q)) { die(mysql_error()); }
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
readfile($file);

Related

Can't play video file with more than 700mb that downloaded using XAMPP

I can't download files that already uploaded in my website, for example :
I already uploaded a video file with 800mb file size and it is okay, the file is save to my directory in the File folder, then I want to download that file again, but as soon as I download the file, I will always got 1kb file not the exact size of the file, and when I play it, nothing happen
this is my code:
<?php
include 'db.php';
if(isset($_REQUEST['name']))
{
$var =$_REQUEST['name'];
$dir = "../files/";
$file = $dir . $var;
if(file_exists($file))
{
header('Content-Description: File Transfer');
header('Content-Type: video');
header('Content-Disposition: attachment;
filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
mysqli_close($conn);
exit();
}
else{
echo "File not found";
}
}
?>
Yeah, I had the same problem too. After searching alot on the internet, I found out that the problem is related to output buffering. The following code solved my problem.
<?php
$file = $_GET['file'];
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_end_clean(); //adding this line solves my problem
readfile($file);
exit;
?>
The code ob_end_clean() basically runs grabs everything in the buffer, then erases the buffer, and turns off output buffering.

Download file program using php on unix box

I have created a beginner program to forcefully download file from unix box to windows through browser, it is not throwing any error but shows nothing on browser just a blank page.
PHP version- 5.2.13
Apache-2.0
Unix Box- HP-UX 11.11 (old version latest is 11.31)
local PC- windows XP Prof.
Browser- IE 7, Mozilla.
Below is my code (this code resides on unix box):
<?php
ob_start();
$file = '/opt/hpws/apache/htdocs/barn/file2';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream;charset=utf-8');
header('Content-Disposition: attachment; filename=$file');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
This line had quotation marks missing:
header('Content-Disposition: attachment; filename=$file');
and in trying to use that line of code, the browser would prompt to save the file as $file.
The line of code should read as:
header('Content-Disposition: attachment; filename="'.basename($file).'"');
The following (tested with a binary file) with file inside the same folder as executed code.
NOTE: You could use header("Content-Type: application/text"); if it's an ASCII file.
<?php
ob_start();
$file = 'file.zip';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream;charset=utf-8');
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));
readfile($file);
exit;
}
?>
Okay, let's add some checks and debugging.
<?php
$file = '/opt/hpws/apache/htdocs/barn/file2';
if (!file_exists($file)) {
die("The file does not exist");
}
if (!is_file($file)) {
die("Not a file"); // Worry about symlinks later
}
if (!is_readable($file)) {
die("The file is not readable");
}
die("DEBUG: Okay, will send the file -- remove this line and retry");
$name = basename($file); // Or anything else
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"{$name}\"");
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit();
?>
If this does not work, it should at least tell you why. Also, on the first run, the one when it will still not download the file but only tell you that it will, check that the page does not contain anything else except that one line. Otherwise, you're setting yourself up for a fall; if not this once, as soon as you have to send a file larger than your output buffers, or too many files for your system memory.

lost connection between PHP server and client while downloading a file successfully

This is my code:
error_log('download start');
readfile('setup.exe');
error_log('download complete');
The file was received successfully but the third line is not executed, its not log the 'download complete'
We facing this problem for a long time we tried also to send chunks (using flush) of this file and after several chunks the connection lost so the rest executable code is not running (but the file received).
We know that the connection is lost by using connection handling in php.
We also set connection time limit to max.
You need to set certain headers first, binary, etc:
$file = 'setup.exe';
if (file_exists($file)) {
error_log('download start');
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));
ob_clean();
flush();
$result = readfile($file);
if ($result) {
error_log('download complete');
}
else {
error_log('unable to download');
}
exit;
}

open encrypted file

I'm looking for a way to open encrypted files that are stored on a server. I'm using mcrypt to encrypt the files.
I was initially going to create a class that would open the file, decrypt it, write it to a new location, then open that. But I have convinced myself there is a better way (I just don't know what it is). It seems like there should be a way to stream it (?) to the browser once it's decrypted.
The initial setup would just link to the file location and the browser would take over (e.g. .pdf files would bring up a dialogue offering to open or save the file). If possible, I'd like it to do the same after decoding.
Pointers? Advice? Bueller?
Thanks!
edit:
This is what is working for now:
function decryptFile($path){
$folder=BASE_PATH.$path.'/'.$this->uri->segment(4);
if(!file_exists($folder.'/tmp')){
mkdir($folder.'/tmp', 0700);
chmod($folder.'/tmp', 0700);
}
$tmpfn=BASE_PATH.$path.'/'.$this->uri->segment(4).'/tmp/'.$this->uri->segment(5);
$p=BASE_PATH.$path.'/'.$this->uri->segment(4).'/'.$this->uri->segment(5);
$pc=file_get_contents($p) or die ('no gfc');
$pcue=$this->encrypt->decode($pc,$this->e_key) or die ('no decode');
$pp=fopen($tmpfn,"w") or die ('no fopen'.$tmpfn);
fwrite($pp,$pcue) or die ('no write');
fclose($pp);
if (file_exists($tmpfn)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($tmpfn));
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: ' . filesize($tmpfn));
ob_clean();
flush();
readfile($tmpfn);
unlink($tmpfn);
exit;
}
}
But another side effect of doing it this way (I guess) is that now instead of getting an open or save dialogue, the only option is to save the file. I'd rather have the option if possible.
edit - final code:
function decryptFile(){
extract($_POST);
$folder = $this->uri->segment(3);
$clientFolder = $this->uri->segment(4);
$fileName = $this->uri->segment(5);
$filePath=BASE_PATH.$folder.'/'.$clientFolder.'/'.$fileName;
$fileContents=file_get_contents($filePath) or die ('Could not get file contents.');
$ue_fileContents=$this->encrypt->decode($pc,$this->e_key) or die ('Could not decode.');
header('Content-Description: File Transfer');
header('Content-Type: '.$type);
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: ' . strlen($ue_fileContents));
echo $ue_fileContents;
exit;
}
Why do you have to write to a temporary file? You can simply do something like this,
function decryptFile($path){
$folder=BASE_PATH.$path.'/'.$this->uri->segment(4);
$tmpfn=BASE_PATH.$path.'/'.$this->uri->segment(4).'/tmp/'.$this->uri->segment(5);
$p=BASE_PATH.$path.'/'.$this->uri->segment(4).'/'.$this->uri->segment(5);
$pc=file_get_contents($p) or die ('no gfc');
$pcue=$this->encrypt->decode($pc,$this->e_key) or die ('no decde');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($tmpfn));
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: ' . strlen($pcue));
echo $pcue;
exit;
}
But another side effect of doing it this way (I guess) is that now instead of getting an open or save dialogue, the only option is to save the file. I'd rather have the option if possible
Try to replace
header('Content-Type: application/octet-stream');
with the actual type of the file. For instance, if it's a PDF:
header('Content-type: application/pdf');
You may also want to drop the line:
header('Content-Disposition: attachment; filename='.basename($tmpfn));
so that no dialog is shown by the browser.

php header download redirect

I'm making a file sharing site for the fun. Trying to make it so that when I hit download, it starts the download. Instead of just a link to /files/$file im trying to do a header redirect:
download.php
/**
* File Download
*/
$query = mysql_query("SELECT id,name,desc FROM files WHERE id = ".intval($_GET['id']));
$row = mysql_fetch_assoc($query);
$file = $row['name'];
if (file_exists($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('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
Filename: <?=$row['name']?>
Desc: <?=$row['desc']?>
Download this file
Im stuck here, what should I do next?
thank you
Do you mean something like this, where the page will display the information about the file and then when the user has clicked th link it will download it?
<?php
$query = mysql_query("SELECT id,name,desc FROM files WHERE id = ".intval($_GET['id']));
$row = mysql_fetch_assoc($query);
$file = $row['name'];
if(!file_exists($file))
{
exit('File does not exist');
}
if(intval($_GET['download'])===1)
{
// Generate the server headers
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($file));
}
else
{
header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize($file));
}
$data = readfile($file);
exit($data);
}
else
{
?>
Filename: <?php echo $row['name']; ?>
Desc: <?php echo $row['desc']; ?>
Download this file
<?php
}
?>
I'm not following what you are asking. A header redirect looks like:
header("Location: /path/to/new/page");
If you want the existing info to download, looks like you need to hit it with an id in your url:
<a href="file.php?id=<?=$file_id ?>">
where $file_id has the id of the file you are looking for. Personally, I'd put that in another file from the page that shows the listing and download link, but YMMV.
You can only do a redirect before any html has been pushed.
Basically after
Filename: <?=$row['name']?>
Desc: <?=$row['desc']?>
Download this file
is sent to the browser, your chance to perform a redirect with php is over. Maybe a Javascript redirect is more appropriate? Tutorial on Javascript redirects.

Categories