I'm developing a web application.
A user can download a specific zip file using readfile() if the zip has been correctly generated.
But since I've integrated the readfile() line, I can't echo anything before or after this line. Here is the code sample causing problem :
if($zip->status == 0){
$zip->close();
$file_url = './zip/'.$userDir.'.zip';
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\"");
readfile($file_url);
echo'
<div class="alert alert-primary" role="alert">
Success
</div>';
}
Everything in the condition is called except for the echo lines at the end. When I remove the readfile($file_url) line, the echo is called.
I also tried to move the echo lines before the line
$file_url = './zip/'.$userDir.'.zip';
And it doesn't work either. Am I missing something ?
If you echo after "sending the file" to the user you are going to corrupt the file.
You have to think as the php code as a download link, the user clicks on it and get a file. Also sending an echo is not going to the user screen since you have this headers
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
I had a similar problem. In my case, a submitted form is generating a pdf file but since automatic download is initiated with readfile() on the action page, HTML of the latter wouldn't load, the browser keeps the form page open - that's where I added an overlay div which becomes visible only after clicking submit, blocking all content except a simple button which takes to the same action page but with the help of GET information, readfile() code isn't running again. Sure a button has to be clicked but it can be a good thing, some sort of download acknowledgement.
It feels, however, a bit odd, loading the same page twice.
Related
I checked similar posts and here's the problem: a portion of my codes :
if($_GET['dl']) {
$file=$_GET['dl'];
$file="../../rep/".$file;
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file) . "\"");
readfile($file);
exit;}
This code runs when user submit form and redirects on current PHP file. The result opens in browser rather than download. I checked a lot of other headers or modifications with no clue.
So I made a separated PHP file : download.php and paste the above code exactly on it. then redirect user to this new file And Problem solved! (File downloads without any problem)
So my question is what's the problem exactly?
Thanks from comments, the reason founded!
I had started the PHP tag <?php from second line in the file like this:
...
php tag start here <?php
Perhaps first line considered as an output.removed first line and now download starts properly ;)
I'm using this bit of code to download a file (path_facture_name) from the server to the client browser :
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($path_facture_name) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Content-Length: ' . filesize($path_facture_name));
ob_clean();
flush();
readfile($path_facture_name);
ob_end_flush();
# ----
# Some other PHP code
# ----
This works just fine, but when the file is downloaded, the script is ended, and the part Some other PHP code will never be executed.
So, my question is, is there a better way to download a file from the server that don't abort the execution of the next part of the code ?
I've tried to use <iframe> or JavaScript code to redirect the window to a sipparate .php file that will handle the download. But that didn't work because this feature that I wanna add is a part of an 18 years old complex php CRM that I can't easily/freely edit.
I'm looking for a PHP solution or guidelines.
Before submitting the form (or whatever takes you to the download page) use javascript to display sg. like "File downloading, press ok" and a button. It will stay because there's no HTML content to be loaded.
Set this button to load your download page again but skipping the file download headers this time (with a get switch).
The answer for this question is #ADyson's comment above :
« "and reload the current php page"...you can't do that, only the browser can do that in this situation. You've already given your response to the request in the form of a file download. The only way to "reload the current page" from the server would be to send some new HTML for the browser to display. But you can't respond to a single HTTP request with both a file download and a HTML document. It's physically impossible. You've already set headers indicating to the browser that the response is a file for download. »
So this is a HTTP limitation. We can't do a multi-part response.
I am creating a csv file to download, using a technique similar to using the browser prompt to download a file
$csv_export = .... csv data...;
header("Content-type: text/x-csv");
header("Content-Disposition: attachment; filename=" . $csv_filename . "");
echo($csv_export);
exit;
The file downloads just fine. But this is in WordPress, so when I do a php exit; everything stops and the page appears to hang, and the user needs to do a page reload.
Is there any way to do this and/or force a reload so that it does not appear to user to have hung?
Thanks
First of all, why do you use exit in the first place to stop the processing? You could output your content like this too:
clearstatcache();
header('Content-Type: '.$type);
header("Content-Disposition: attachment; filename=".$filename);
header('Content-Length: ' . filesize($path));
readfile($path);
If you really want the processing to stop and didn't send any HTML content you can just use the header redirect:
header("Location: http://example.com/myOtherPage.php");
die();
If you already send content, you could use JavaScript to reload, but I can't give you an example without more context/code.
I'm finding Headers a nightmare to get my head around, I have a file the user downloads which works fine. However I then whish to echo to the screen that xx file has been sent; but ofc this echo is just placed inside the sent file.
Full dowload code is as follows:
function download()
{
$orderNo = $_POST['orderNo'];
$lines = file('F:/xamptest/htdocs/UniProject/upload/Amazon output.txt');
$lineCount = count($lines);
if($orderNo>0&&$orderNo<=$lineCount)
{
$lineEx = explode("\t", $lines[($orderNo-1)]);
$file = fopen('Order.txt', 'w');
fwrite($file, $lineEx[8].PHP_EOL .$lineEx[17].PHP_EOL .$lineEx[18].PHP_EOL .$lineEx[19].PHP_EOL .$lineEx[20].PHP_EOL .$lineEx[21].PHP_EOL .$lineEx[22].PHP_EOL .$lineEx[23].PHP_EOL);
fclose($file);
$file = 'Order.txt';
ob_end_clean();
header("Cache-Control: private");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
readfile($file);
echo "Current order, number: ".$orderNo."<br> Has been downloaded";
}
else
{
echo "Please enter a valid Order Number between 1 and ".$lineCount;
}
}
I can't seem to find how to stop the headers without using exit(); which then still means it won't show the echo, and any more use of ob_end_clean(); in any other ways causes the sent file to be empty. Only other thing I could think was having the echo in its own function, but as it runs at the same time the headers do it still places it in the file.
Many thanks for any help - Tom.
What you're dealing with is an HTTP request. The browser requests a URL with an HTTP request, the server sends a response. Click a link → browser sends request → server sends HTML page in response. Use Chrome, Safari or Firefox + Firebug and play around with the Network tab in their Web Inspector/development tools to get a real feeling for what's happening.
If you want to download a file, it works the same way. Only the server tells the browser through HTTP headers that this response is not an ordinary HTML page, but is supposed to be a file which it should save on disk.
As you should be able to see, there's no way to respond with a file download and an HTML page at the same time in one response. There's simply no way to do it. You have to output your HTML page with the message first, then link to the file download from there.
I am using the following code in a php document to force download of a pdf form since the submission works only after you have it on your local machine rather online.
It downloads the file ok but it corrupts it.
I can no longer open the pdf document.
<?php
$file_name = 'costumer.pdf';
$file_url = 'http://www.lopezi.com/forms/' . $file_name;
header('Content-Type: application/pdf');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);
?>
The Content-Transfer-Encoding header shouldn't be needed in this case. Further I suspect that you have corruption in the outputted file.
Download it somewhere, open notepad, and drag the file in there. If any PHP warnings or errors were generated you will see them at the top.
Also, try to avoid the option of having more content return from the script, causing problems with the download, end with something like:
die(file_get_contents($file_url));
This way you cannot accidentally break the code easily by adding more output.