Search code examples
phplaravellaravel-excel

Returned data from Laravel for Downloading Excel file is nonsense, How to fix it?


I have project which i'm using vue.js in blade file, and for exporting excel, i'm trying to this method, which giving a response like this :

enter image description here

Here's the Code Structure:

In Blade.php(There's a buttin which it's getting startDate, endData, to get Result :

<button v-if="db_query!=null" @click="save_excel()"  id="send" type="button" class="btn btn-success">Export</button>
save_excel:function(){
            let self=this;
            let start_at=$('#start_at').val();
            let end_at=$('#end_at').val();
            $.ajax({
                type: "post",
                url: "{{route('report.save_as_excel')}}",
                data: {
                    _token:"{{csrf_token()}}",
                    name            :self.name,
                    created_at      :self.created_at,
                    file_id         :self.file_id,
                    order           :self.order,
                    paid_price      :self.paid_price,
                    phone           :self.phone,
                    price           :self.price,
                    products        :self.products,
                    products_desc   :self.products_desc,
                    products_order_desc       :self.products_order_desc,
                    reagents        :self.reagents,
                    status          :self.status,
                    time_id         :self.time_id,
                    unpaid_price    :self.unpaid_price,
                    check_box       :self.check_box,
                    'end_at'        :end_at,
                    'start_at'      :start_at,
                    },
                success: function (response) {

                    self.result=response.customers;
                    console.log(response);  
                    window.open(response);
                }
            });
},

CustomerAtlasExports.php

class CustomerAtlasExports implements FromQuery, Responsable
{
use Exportable;

public $start;
public $end;
public $where;

private $fileName = 'Gozaresh.xlsx';
public function __construct($start,$end,$where)
{
    $this->start = $start;
    $this->end = $end;
    $this->where = $where;
}

public function query()
{
    return Customer::with(['products','reagents'])->whereBetween('created_at',[$this->start,$this->end])->where($this->where)->get();;
}

}

Controller.php :

$where=$this->c_query_builder();
 $start=Carbon::createFromTimestamp(substr($request->start_at,0,10))->hour(0)->minute(0)->second(0);
 $end=Carbon::createFromTimestamp(substr($request->end_at,0,10))->hour(23)->minute(59)->second(59);

return (new CustomerAtlasExports($start,$end,$where));

In documentation as they've explained i should get file to download it, i've also tried to use ->Download in controller instead of Responsable in Export file.


Solution

  • You can't download files via AJAX. The data ends up in a JavaScript variable in your web page, not as a file on your disk. (Well sometimes there's a way to fudge it with some JavaScript it but it's not recommended and might not always work).

    The normal approach, if you want to initiate a download via JavaScript, is to use window.open() or window.location to open a new URL in the browser directly which causes the download to happen. Then it's done via a regular request and not an ajax, and is handled in the way you expect.

    In your case, if you're posting data to be turned into an Excel file, I would make the PHP return a URL as the response to the AJAX request. That URL will point to where the Excel file has been saved on the server. Then in the "success" callback of the AJAX request code, use JavaScript (as described above) to tell the browser to visit that URL.

    N.B. You might want to also consider a cron job or something on the server to tidy up old Excel files after a period of time. Perhaps you could give the user guidance that their download URL will only be valid for a certain number of hours or days, before you delete the file. Then your disk won't get full of old junk files.