Prevent multiple connections while file download in php - php

There is a PHP function download() that allows user to download the file. The decrypted file is created on server and provided to user using readfile($file) . But when Internet Download Manager downloads it using multiple connections, it makes multiple connections and that file is created multiple times on the server, one for each connection. What could be the best possible solution to create only one file for single user, even when there are multiple requests for download. And after download the should be deleted also.
Following is the sample code for download.
public function download($new_filename,$original_filename){
$fp2=fopen($new_filename,'wb'); //create empty file name $new_filename
fputs($fp2,base64_decode(file_get_contents($original_filename)));//decoding and writing to $fp2
header('Content-Description: File Transfer');
header("Content-Type: application/".$ext);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Disposition: attachment; filename="' . $new_filename . '"');
header("Content-Length: " . filesize($new_filename));
ob_clean();
flush();
readfile($new_filename);
/***** removing temporary decoded file ****/
if(file_exists($new_filename)) {
chmod($new_filename,0777); //Change the file permissions if allowed read and write and execute
unlink($new_filename); //remove the file
}
fclose($fp2);
}

I guess the easiest way to accomplish what you want is something like this:
Generate unique download urls with a "ticket" that gives one time access to the file (eg. dl.php?file=ABC123&ticket=1231292), store this ticket in a database or some other structure when you generate it, so that you can invalidate it when the download begins.
In your download script you check if the ticketid is valid, if not you respond with a 403 HTTP status.
If it is valid then begin generating the file etc., invalidate the ticket and then start to send the file to the client.

Maybe you can use base64_decode and file_get_contents instead of readfile like:
public function download($new_filename,$original_filename) {
header('Content-Description: File Transfer');
header("Content-Type: application/".$ext);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Disposition: attachment; filename="' . $new_filename . '"');
header("Content-Length: " . filesize(base64_decode(file_get_contents($original_filename))));
echo base64_decode(file_get_contents($original_filename));
}
And you can add something to lock 1 connection by ip address using $_SERVER['REMOTE_ADDR']

Related

How force download an .xlsx file in PHP without having it corrupted?

None of the already existing questions have helped me.
I'm trying to force download an excel file with the file type .xlsx. It works perfectly fine in a download code like this:
echo "<a href='" . $dateiname . "'>Datei herunterladen</a>";
But whenever I try to make a forced download, it doesn't work. I've tried various headers from various questions on stackoverflow, the last two being
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $dateiname . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Pragma: no-cache');
header('Content-Length: ' . filesize($dateiname));
$objWriter->save('php://output');
and
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Transfer-Encoding: binary ");
header('Content-Disposition: attachment; filename='.basename($dateiname));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($dateiname));
$objWriter->save('php://output');
I tried both in the same file as where I create the file, but also in a separate file, but either way I always get the error:
Excel cannot open the file (filename) because the file format or file extension is not valid. Verify that the file has not been corruted and that the file extension matches the format of the file.
The file itself on my server seems perfectly fine.
I've found how I used PHPExcel to force downloading an xlsfile.
header("Content-Disposition: attachment; filename={$fileName}.{$fileFormat}");
header("Content-Type: application/vnd.ms-excel;");
header("Cache-Control: max-age=0");
$objWriter->save('php://output');
Hope it helps.

Prompt the user to save html file to the folder they select on their computer

I have a piece of code to let the user save a html file (the 'history' list of his actions in the site) to the folder or location he wants on his/her computer. It's a start but it just saves the file on the Download folder of the browser used.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment;filename="'.basename($hFile).'"');
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($hFile));
ob_clean();
flush();
readfile($hFile);
Do you know what is missing in order to let the user choose where to save this file?
This sort of behavior is browser-dependent and you have no control over it.
You've done what you can do to force a download. Now, it's up to the user, their browser, and configuration.

How do I force download of a file through Flysystem?

I may be missing something exceptionally obvious here, but I'm using yii2-flysystem along with Dropbox to read and write files.
I can upload and write them to Dropbox with no problem but then, when reading like this:
$file = Yii::$app->dropboxFs->read($fn);
..all that gives me is a string (/tmp/phpQkg8mJ).
How do I actually force the download of the file that I'm reading? I'm not sure what that temporary file location actually relates to.
Try function readfile().
According to example, your code should be looks something like this:
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));
readfile($file);
exit;
}

PHP force downloading

How do I make php force download a file. I have a file named song1, which is a song, in the file songs. so from the page I am at it is song/song1. How do I make php download the file as soon as the php is ran?
You have to send out some HTTP headers:
header('Content-disposition:attachment; filename=song.mp3;');
Then you have to pull the song data with for example file_get_contents(). And finally use a die() or exit() to avoid adding extra data.
Side note: The above code will not work if you've already sent out HTTP headers (wrote out some whitespace characters, etc), so put it directly after <?php if you can.
Try below code
$file='song1.mp3';
if (file_exists('song/'.$file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('song/'.$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('song/'.$file));
ob_clean();
flush();
readfile('song/'.$file);
}
It will directly download file.

Allow users to view and download files from server

I'd like users to be able to view files (I need to research this further, PDF/doc viewer, vid player etc) on the site before choosing to download them. Any suggestions on suitable methods?
The main question though is allowing them to download files.
I read on another SO post that this:
<?php
$file = 'monkey.gif';
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;
}
?>
is suitable however I'll be pulling the file name from the database. I'm thinking of using a standard download page so that download.php?filename=thisFileToDownload can pass the filename along.
The other issue is that there are different file types such as images, videos, excel, docs and pdfs etc etc. Are there any problems that I might run into with this?
Thanks for any help

Categories