How To Return String To Client After Setting Header
Solution 1:
You can not. Don't waste your time trying to look for a hack, rather design your download page accordingly.
When you tell a browser (using headers) that you are going to provide a file to download like here
$this->response->setHeader('Content-Type', "application/force-download", TRUE);
Then all fairly recent browsers will follow that advice and download the file, after that they don't care if PHP manages to echo something at the end or not, they don't need it.
Your PHP code is not being ignored, it is processing just fine. PHP does not stop you from having any code after you provide some headers for the browser. Its just that once you have told the client that you are going to return a file to download it does not bother what other text you wanted to output. In fact that would be considered part of the download file. You don't see it in your file because its a return
which is not useful in this content, try an echo
.
When you provide a Content Type header then you are expected to send the content exactly of that type if you want the browser to successfully understand your server's response.
Look at all the major download sites, almost all of them have their downloads setup so that when you click a download link you are redirected to another page which says "Your download will begin shortly..." and meanwhile they initiate another request to their download page which does just that; provides the file to download.
So in one request you can't mix the two together successfully with any fair amount of browser compatibility.
Solution 2:
To end the current script you can use return
, however when used in the top level script (as you have it) it will end execution but not pass back any return value or output anything as part of the HTTP response. You need exit
for this (but see later).
return
can only pass back a value to calling scripts:
- when used in an include/require, it will end that include/require and pass value back to calling script
- when used in a function, it will end that function and pass value back to calling script
To end the current script and output a value as part for the HTTP response, you can use exit
(http://php.net/manual/en/function.exit.php) or die
(same as exit). But exit
can change its behaviour when you pass a parameter:
- if a string, it will send as part of the HTTP response
- if an integer, it will use this as an exit code (for command line usage).
To output anything to get "returned" as part of the HTTP response, use echo
. (http://php.net/manual/en/function.echo.php). This will output anything that can be converted to a string (i.e. to output an integer or a string) and not change behaviour if an integer or string as exit
will.
The safest option is therefore:
- always use
echo
to send something back as part of the HTTP response - always use
exit
to end execution; - use return inside functions or files you know will be "included" (and optionally pass back a return value)
Ideally (to avoid potential ambiguation in the code) for an HTTP response, don't add return values to exit unless you're programming for a command line interface. i.e. for HTTP, use
// Outputs something and existsecho'TEST';
exit;
or
// Outputs something and existsecho1;
exit;
If you're outputting a file (and not a variable you have in memory) look at readfile()
(http://php.net/manual/en/function.readfile.php) which will output a file stream to the HTTP response. (Followed by exit;
)
// Outputs a file to HTTP response
readfile('/path/To/My/File/MyFile.txt');
exit;
*Bonus note: exit
, echo
and return
are not functions, per se, but are language constructs. The return values for exit
and return
should not be specified in parenthesis. It'll work, but the PHP manual recommends against it. echo
can use parameters, and indeed you must if you're passing more than one value to be output.
Wrong:
- exit('TEST');
- return('TEST');
Correct:
- exit 'TEST';
- return 'TEST';
- echo 'TEST';
- echo ('TEST', 'MORE'),
Solution 3:
Well I am using MVC framework and in my controller I have a method that does this and there is no need to re-load the parent page from where download initiated:
// Define headersheader("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file_name");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// Read the filereadfile($filePath);
exit;
Post a Comment for "How To Return String To Client After Setting Header"