henock_barakael's avatar

How to read filename from response?

I try this

Small code from my controller

public function export(){
$headers = [
            'Content-Type'        => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Content-Disposition: attachment; filename='.$fileName,
        ];
return new Response('',200,$headers);
}

My js

<script>
    $('#export').click(function(e){

            e.preventDefault();

            var dateStart=document.getElementById('start_date').value;
            var dateEnd=document.getElementById('end_date').value;
            var action = $(".action:checked").val();
            var method = $(".method:checked").val();
                $.ajax({
                    url: "{{route('spatie.export')}}",
                    method: 'POST',
                    data: { _token: "{{csrf_token()}}" ,dateStart: dateStart,dateEnd: dateEnd,action: action,method: method},
                    xhrFields: {responseType: "blob",} ,
                    success:function(response){
                        var blob = new Blob([response]);
                        var link = document.createElement('a');
                        const filename = response.headers.get('content-disposition')
      .split(';')
      .find(n => n.includes('filename='))
      .replace('filename=', '')
      .trim()
    ;
                        link.href = window.URL.createObjectURL(blob);
                        link.download = filename;

                        document.body.appendChild(link);
                        link.click();
                    },                      

                });
        
    });
</script>

But now i'm getting this error

Uncaught TypeError: response.headers is undefined

0 likes
4 replies
LaryAI's avatar
Level 58

The error is occurring because the response object does not have a headers property. To get the filename from the response, you can modify the controller code to include the filename in the response body and then extract it in the JavaScript code. Here's an example:

Controller code:

public function export(){
    $fileName = 'example.xlsx';
    $headers = [
        'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'Content-Disposition' => 'attachment; filename='.$fileName,
    ];
    $data = [
        'filename' => $fileName,
        // add any other data you want to include in the response
    ];
    return response()->json($data, 200, $headers);
}

JavaScript code:

$.ajax({
    url: "{{ route('spatie.export') }}",
    method: 'POST',
    data: {
        _token: "{{ csrf_token() }}",
        dateStart: dateStart,
        dateEnd: dateEnd,
        action: action,
        method: method
    },
    xhrFields: { responseType: "blob" },
    success: function(response) {
        var blob = new Blob([response]);
        var reader = new FileReader();
        reader.onload = function() {
            var data = JSON.parse(reader.result);
            var filename = data.filename;
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = filename;
            document.body.appendChild(link);
            link.click();
        };
        reader.readAsText(response);
    }
});

In this code, we're using response()->json() to send a JSON response with the filename included. In the JavaScript code, we're using FileReader to read the response as text and then parse the JSON data to get the filename. We can then use the filename to set the download attribute of the download link.

Snapey's avatar

where does $filename magically come from in your controller?

Please or to participate in this conversation.