Laravel streamDownload/download, storage::download/put all returning file as response string instead of download

The file that I am generating is being returned in the response as a string instead of prompting the download.

I’ve seen and tried a couple approaches to it from stackoverflow / other websites and they ultimately all resulted in the exact same problem.

I’ve tried:

  1. Making a temp file, writing to it, then moving it to a new location with Storage::put and downloading from that location using response()->download.
  2. Writing to a temp file and echoing/reading it in the streamDownload closure.
  3. Writing to a temp file and reading it after finishing (while setting the Headers beforehand)

I am POSTing a form payload using Axios with the headers

'content-type': 'multipart/form-data',
'X-CSRF-TOKEN': 'csrfToken'

The headers I am using for the response are:

'Content-Type: text/csv',
'Content-Disposition: attachment; filename=myFile.csv'

I’ve tried setting the headers using header() and by creating an array then passing it to streamDownload/download as header arguments.

The file download works/prompts normally if I simply create a form and submit it with form.submit(). I am only experiencing this problem when I try to do it asynchronously via a direct post request with Axios.

I am at a complete loss for what is causing this discrepancy, since submitting the form normally prompts the download just fine.

Answer

I managed to solve this by using the returned response and creating a BLOB with it and prompting the download using the BLOB.

 let config = {
     headers: {
         'content-type': 'multipart/form-data',
         'responseType': 'blob',
         'X-CSRF-TOKEN': csrfToken
     }
 };
            

axios.post(downloadRoute, payload, config).then(response => {
    const downloadUrl = window.URL.createObjectURL(new Blob([response.data.fileOutput]));
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.setAttribute('download', 'myfile.csv');
    document.body.appendChild(link);
    link.click();
    link.remove();
});

Hope this helps anyone in the same situation!