php - How can I have a header('Location: ') in the same page as a csv file creation and output or create this csv file in an html based page?
Get the solution ↓↓↓My app collects data using a series of forms, then this data is sent and processed using external API's. You can think of the structure asform>processingForm.php>form2>processingForm2.php ...
After all the info needed has been collected and the app is located at the last processing/sending page I faced an issue. Since there can't be any data output before aheader('Location: ')
I found myself trapped forever in that processing, htmless page with the csv being correctly downloaded. So I had my file but at the price of not being able to continue the process.
I thought about storing the values I needed to write onto the csv inside$_SESSION
in order to retrieve them at the last page of the project, so it would not interfere with other outputs, but when I tried for the first time I saw that the page's html did not appear. This was of course produced due to php being loaded first, so the csv would be created and the page left completely blank.
How can I solve this issue? I want my csv file as well as any html at least as a last page. I would redirect directly to the start again and forget about that last page, but I also can't. The only thing I know would work is leaving that empty page even without a mere button to go back to the start. I guess there must be some kind of workaround to this.
I've also tried printing the last page using php -> Same thing happened since I was outputing the page as a whole. I have error reporting enabled.
This is that final page I've been talking about but once again it's not necessary, a way to simply redirect after the csv has been downloaded would be fine too.
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (!isset($_SESSION['logged']) || empty($_SESSION['logged']) || $_SESSION['logged'] != 1) {
header('Location: url');
}
$arrayCsv = $_SESSION['arrayCsv'];
$filename = $_SESSION['companyName'];
$filename = strtolower(str_replace(' ', '', $filename));
$filename = $filename.'.csv';
header('Content-Type: application/csv');
header("Content-Disposition: attachment; filename=$filename");
$fp = fopen("php://output", 'w');
$delimiter = ',';
$enclosure = '"';
$escape_char = "\\";
foreach ($arrayCsv as $customerCsv) {
fputcsv($fp, $customerCsv, $delimiter, $enclosure, $escape_char);
}
fclose($fp);
?>
<!DOCTYPE html>
<html lang="es">
<head>
<title>Fin</title>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="../style/homeStyleSheet.css">
</head>
<body>
<!--NAVBAR-->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="../index.php"><img id="ubunetLogo" src="../img/logo-color.svg"></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="../index.php">Inicio<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="./createContact.php">Crear<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#">Actualizar<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#">Eliminar<span class="sr-only">(current)</span></a>
</li>
</ul>
</div>
</nav>
<!--BODY-->
<div id="finalPageContainer">
<div class="row">
<a href="../pages/createContact.php"></a>
<p id="finalPageP">Todos los datos se han insertado con éxito. Volver a crear contacto.</p>
</div>
</div>
<footer id="sticky-footer2" class="py-4">
<div class="container text-center">
<small>Copyright © Ubunet</small>
</div>
</footer>
</body>
</html>
Answer
Solution:
As @cBroe suggested in the comments, I was trying to obtain two different resources in one request. Those resources being:
- The csv file.
- The HTML/New page
This is not possible, so in order to trick the app a little bit I created a link in the final page that takes you to the same page with a variable to discern wether to download the csv or just show the view. This way the body now looks like this:
<!--BODY-->
<button id="finalPageContainer" onclick="location.href='http://10.200.210.61/index.php'" type="button">Todos los datos se han insertado correctamente. ¡Volver a inicio!</button>
<div id="finalPageContainer2">
<a id="getCsvLink" href="http://10.200.210.61/views/finalPage.php?getCsv=1">Obtener CSV</a>
</div>
<footer id="sticky-footer2" class="py-4">
<div class="container text-center">
<small>Copyright © Ubunet</small>
</div>
</footer>
This is also possible by adding this code at the beginning:
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (!isset($_SESSION['logged']) || empty($_SESSION['logged']) || $_SESSION['logged'] != 1) {
header('Location: '.$url);
}
if (isset($_GET['getCsv']) && $_GET['getCsv'] == 1) {
$arrayCsv = $_SESSION['arrayCsv'];
$filename = $_SESSION['companyName'];
$filename = strtolower(str_replace(' ', '', $filename));
$filename = $filename.'.csv';
header('Content-Type: application/csv');
header("Content-Disposition: attachment; filename=$filename");
$fp = fopen("php://output", 'w');
$delimiter = ',';
$enclosure = '"';
$escape_char = "\\";
foreach ($arrayCsv as $customerCsv) {
fputcsv($fp, $customerCsv, $delimiter, $enclosure, $escape_char);
}
fclose($fp);
die();
}
Thedie()
at the end is very important for it prevents the html from leaking to the csv file, so the only thing written onto it are the values I need.
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: can't write image data to path
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.