PHP generate file for download then redirect

PhpRedirectHeader

Php Problem Overview


I have a PHP app that creates a CSV file which is forced to download using headers. Here's the relevant part of the code:

header('Content-Type: application/csv'); 
header("Content-length: " . filesize($NewFile)); 
header('Content-Disposition: attachment; filename="' . $FileName . '"'); 
echo $content;
exit(); 

What I'd like to do is redirect users to a new page after the file is built and the download prompt is sent. Just adding header("Location: /newpage") to the end didn't work, expectedly, so I'm not sure how to rig this up.

Php Solutions


Solution 1 - Php

I don't think this can be done - although I am not 100% sure.

The common thing (e.g. in popular download sites) is the reverse: first you go to the after page and then the download starts.

So redirect your users to the final page that (among other things) says:

Your download should start automatically. If not click [a href="create_csv.php"]here[/a].

As about initiating the download (e.g. automatically calling create_csv.php) you have many options:

  • HTML: [meta http-equiv="refresh" content="5;url=http://site/create_csv.php"]
  • Javascript: location.href = 'http://site/create_csv.php';
  • iframe: [iframe src="create_csv.php"][/iframe]

Solution 2 - Php

very easy to do in the case it is really needed.

But you will need to have a bit work in JavaScript and cookies:

in PHP you should add setting up a cookie

header('Set-Cookie: fileLoading=true'); 

then on the page where you call the download you should track with JS (e.g. once per second) if there is coming cookie like that (there is used plugin jQuery cookie here):

setInterval(function(){
  if ($.cookie("fileLoading")) {
    // clean the cookie for future downoads
    $.removeCookie("fileLoading");

    //redirect
    location.href = "/newpage";
  }
},1000);

Now if the file starts to be downoaded JS recognizes it and redirects to the page needed after cookie is deleted.

Of course, you can tell you need browser to accept cookies, JavaScript and so on, but it works.

Solution 3 - Php

The header you are sending are HTTP headers. The browser takes that as a page request and processes it as a page. And in your case, a page it needs to download.

So adding a redirect header to that confuses the whole process of downloading the file (since headers are collected, generated into one header and then sent to the browser, you can try this by setting multiple redirect headers IIRC)

Solution 4 - Php

This is quite old issue, but here is how I achieved it via JS.

// Capture the "click" event of the link.
var link = document.getElementById("the-link");
link.addEventListener("click", function(evt) {
  // Stop the link from doing what it would normally do.
  evt.preventDefault();
  // Open the file download in a new window. (It should just
  // show a normal file dialog)
  window.open(this.href, "_blank");
  // Then redirect the page you are on to whatever page you
  // want shown once the download has been triggered.
  window.location = "/thank_you.html";
}, true);

Via - https://www.daniweb.com/web-development/php/threads/463652/page-not-redirecting-after-sending-headers-in-php

Solution 5 - Php

Bear in mind, however, the automatic initiation of downloadable files for IE users will trigger the security warning tab. All three of the methods outlined by daremon would show this warning. You simply can't get around this. You will be better served if you provide real links.

Solution 6 - Php

<?php 
	function force_file_download($filepath, $filename = ''){
		if($filename == ''){
			$filename = basename($filepath);
		}

		header('Content-Type: application/octet-stream');
		header("Content-Transfer-Encoding: Binary"); 
		header("Content-disposition: attachment; filename=\"" . $filename . "\""); 
		readfile($filepath); // do the double-download-dance (dirty but worky)	
	}

	force_file_download('download.txt');
?>
<script type="text/javascript">
	location = 'page2.php'
</script>

Here is a solution using javascript.

Solution 7 - Php

I found one workaround for this that relies on javascript, so it's not exactly secure, but for non-secure critical sites it seems to work.

Have a form with a button titled 'download' with the action set to point to the download script, then using javascript put something on the onsubmit handler that strips out the download button and replaces the messaging on the screen. The download should still happen and the screen will change. Obviously, if there's an issue with the download script then it still looks like the download was successful even if it doesn't fire, but it's the best I've got right now.

Solution 8 - Php

Update: New Solution:

<a id="download-link" 
   href="https://example.com/uploads/myfile.pdf" 
   class="btn">Download</a>

<script>
    jQuery(document).ready(function(  ) {
        jQuery("#download-link").click(function(e) {
			e.preventDefault(); 
			var url = jQuery(this).attr('href');
			var _filename = url.split('/');
			_filename = _filename[_filename.length - 1];
			console.log(_filename);
		
			fetch(url, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json; charset=utf-8'
				},
			})
			.then(response => response.blob())
			.then(response => {
				const blob = new Blob([response], {type: 'application/pdf'});
				const downloadUrl = URL.createObjectURL(blob);
				const a = document.createElement("a");
				a.href = downloadUrl;
				a.download = _filename;
				document.body.appendChild(a);
				a.click();
			});
		
		});
	});
</script>

Source

Old answer:

Here is the answer:
It's work!
You need three different parts of code:

HTML

<a id="download_btn" class="btn btn-primary" href="?file=filename&download=1">Download<&/a>


JQuery

$('#download_btn').click(function(){
	window.location.href = '<?=base_url()?>/?file=<?=$file;?>&download=1';
}).focusout (function(){
	window.location.href = '<?=base_url()?>';
	return false;
});


PHP

		if(isset($_GET['download']) && isset($_GET['file'])){
			
			$zip_path = 'path_to/'.$_GET['file'].'.zip';

			if(file_exists($zip_path)){
				header('Content-Type: application/zip');
				header('Content-Disposition: attachment; filename="'.basename($zip_path).'"');
				header('Content-Length: ' . filesize($zip_path));
				header('Location: '.$zip_path);
			}

		}

Solution 9 - Php

You can try and redirect to the URL plus a parameter that represents the file contents. And in the redirect, you can output the file content for download.

Solution 10 - Php

Launch the PHP file which contains the CSV download using:

<a onclick="popoutWin(\'csvexport.php\')" >Download CSV File</a>

or

<input name="newThread" type="button" value="Download CSV File"
        onclick="popoutWin(\'csvexport.php\')" />

where the JavaScript function popoutWin is

/*
 * Popout window that self closes for use with downloads
 */
function popoutWin(link){
	var popwin = window.open(link);
	window.setTimeout(function(){
	    popwin.close();
	}, 500);
}

This will open a window, to display the CSV download prompt and then immediately close the window, leaving only the prompt.

Solution 11 - Php

Hmmmm...

Put the code below in the main javascript of the site.

 if (window.location.pathname == '/url_of_redirect/') {
        window.open(location.protocol + '//' + location.hostname + '/url_of_download.zip', '_parent');
    }

Explaining: It does the normal redirect with php to some url you will difine and in javascipt it says: If the pathname is the same as the path that redirect made '/url_of_redirect/' then it opens the url on a new page, generating the downlod.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEvanView Question on Stackoverflow
Solution 1 - PhpdaremonView Answer on Stackoverflow
Solution 2 - PhpsmnbbrvView Answer on Stackoverflow
Solution 3 - PhpÓlafur WaageView Answer on Stackoverflow
Solution 4 - PhpVaibhav JainView Answer on Stackoverflow
Solution 5 - PhpmartarView Answer on Stackoverflow
Solution 6 - PhpnikksanView Answer on Stackoverflow
Solution 7 - PhpDarren CrabbView Answer on Stackoverflow
Solution 8 - PhpHisham DalalView Answer on Stackoverflow
Solution 9 - Phpuser1251795View Answer on Stackoverflow
Solution 10 - PhpClintonView Answer on Stackoverflow
Solution 11 - PhpFernandoGirotoView Answer on Stackoverflow