title: Laravel 5.8 StreamDownload File Attachment Redirecting Instead of Downloading
body: <p>I think I'm making a mistake that I'm not seeing in my Laravel controller. I have JSON data that I want to spit into a CSV, and then download that file in the browser.</p>
  <p>I'm submitting a form with hidden inputs to POST data to the server, running queries for the data, then using fputcsv() to create a file stream callback, and returning a Laravel Stream Response.</p>
  <p>I want to stream download it, and not write a file on the server to download. I'm aware of tricks to use ajax or blobs to do this instead, but I feel like a form POST to download a CSV file should be pretty simple and I'm doing something stupid. If I return just the raw data, the CSV strings look correct, so I don't think it's an issue with the processing or data itself.</p>
  <p><strong>ExportController</strong></p>
  <pre><code>protected function csvFileHeaders($filename) {
      return array(
          &quot;Content-type&quot; =&gt; &quot;text/csv&quot;,
          &quot;Content-Disposition&quot; =&gt; &quot;attachment; filename=&quot;. $filename,
          &quot;Pragma&quot; =&gt; &quot;no-cache&quot;,
          &quot;Cache-Control&quot; =&gt; &quot;must-revalidate, post-check=0, pre-check=0&quot;,
          &quot;Expires&quot; =&gt; &quot;0&quot;
      );
  }
  
  public function __invoke() {
  
  $filename = 'report_'.$endpoint.'_'.date('d-m-Y-H:i:s').'.csv';
  $headers = $this-&gt;csvFileHeaders($filename);
  
  $data    = $rows-&gt;toArray();
  $columns = collect(request()-&gt;input('params.columns'))-&gt;map(function($c) {
      return $c['label'];
  })-&gt;toArray();
  $fields = collect(request()-&gt;input('params.columns'))-&gt;map(function($c) {
      return $c['value'];
  })-&gt;toArray();
  
  $callback = function() use ($data, $fields, $columns) {
      $file = fopen('php://output', 'rw');
      fputcsv($file, $columns);
  
      foreach($data as $d) {
          // MAP values to columns OR empty strings if value is not present
          fputcsv($file, collect($fields)-&gt;map(function($f) use ($d) {
              if ( array_key_exists($f, $d) ) { return $d[$f]; }
              return '';
          })-&gt;toArray());
      }
  
      fclose($file);
  };
  
  
  return response()-&gt;stream($callback, $filename, $headers);
  
  }
  </code></pre>
  <p><strong>Frontend React POST Form</strong></p>
  <pre><code>&lt;form id=&quot;report-export-form&quot; action={'/report/export'} method=&quot;POST&quot;&gt;
      &lt;div dangerouslySetInnerHTML={{ __html: csrf_token }} /&gt;
      {/* BECOMES */}
      {/* &lt;div&gt;&lt;input type=&quot;hidden&quot; name=&quot;_token&quot; value=&quot;...token value...&quot;&gt;&lt;/div&gt; */}
  
      &lt;input type=&quot;hidden&quot; name=&quot;mode&quot; value={form.mode)} /&gt;
      &lt;input type=&quot;hidden&quot; name=&quot;endpoint&quot; value={endpoint} /&gt;
  
      &lt;button className=&quot;btn btn-success&quot; type=&quot;submit&quot;&gt;
          Export to CSV
      &lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  <p>What happens instead of a file download is the page redirects (refreshes to the original page) and no file is downloaded. Does anyone see what mistake I'm making?</p>