-1

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.

Mohammad Eskandari
  • 221
  • 1
  • 5
  • 14
  • 2
    that looks like binary data, which is what you'd expect an Excel file to contain (since it's a binary format). What were you expecting to see? – ADyson Mar 21 '19 at 13:42
  • 2
    You probably need to set the content type header and force it to xls/xlsx. – aynber Mar 21 '19 at 13:43
  • @ADyson returned data from query in table in excel. – Mohammad Eskandari Mar 21 '19 at 13:43
  • @aynber i want to make it downloadable when use click on export button. – Mohammad Eskandari Mar 21 '19 at 13:44
  • 4
    You mean you expected an Excel file to open on your computer? you can't download files via ajax, you realise that? The data ends up in a Javascript variable, not 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. – ADyson Mar 21 '19 at 13:44
  • 2
    TBH though, this code: `return (new CustomerAtlasExports($start,$end,$where));` all it does is create a PHP object and return it. I can't see where it actually does anything related to creating an Excel file?? – ADyson Mar 21 '19 at 13:47
  • @ADyson in their documentation they've did it like this, created file base on this code. now i want to make it downloadable. how to do that? – Mohammad Eskandari Mar 21 '19 at 13:53
  • Can you give a link to this page of documentation? Anyway I'd expect the basic idea would be to make the Controller return a URL to where the file is saved on the server, and then in the "success" use a window.open() or window.location call to redirect the browser to that URL - as I already mentioned above. – ADyson Mar 21 '19 at 13:55
  • Or, just don't use AJAX at all, and instead make a normal request to Controller.php in the first place. The only problem you've got with that is you're using POST and passing a lot of data, so using a regular browser GET request might not be practical or desirable. So probably my first suggestion is better. – ADyson Mar 21 '19 at 13:55
  • @ADyson https://docs.laravel-excel.com/3.1/exports/from-query.html here's the link – Mohammad Eskandari Mar 21 '19 at 13:56
  • In that code example in the documentation it seems you have to call the `->download` method, whereas you just created the object. Look at it more closely! But even then, download via ajax will still not work. – ADyson Mar 21 '19 at 14:00
  • @ADyson in document there's 2 way to download the file, first is to use ->download, second is to use Responsable in Export file as i've mention at top. i've also used normal request, got another problem. i'm not really expert at this, still learning. i've tried to return Storage::url('export.xlsx'), it's not working. – Mohammad Eskandari Mar 21 '19 at 14:04
  • The link you gave me doesn't mention the word "Responsable" anywhere. All the examples on the page use the "->download" method. But it was only an aside. The important point is that you **can't download files via AJAX**. – ADyson Mar 21 '19 at 14:07
  • I assume you're talking about this: https://laravel-news.com/laravel-5-5-responsable. But unless you've missed some code out of your class above, it doesn't actually implement that interface. – ADyson Mar 21 '19 at 14:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190443/discussion-between-mohammad-eskandari-and-adyson). – Mohammad Eskandari Mar 21 '19 at 14:10
  • @ADyson well i've change it to normal request. now it's working. Thanks. if u answer it, i'll mark it. – Mohammad Eskandari Mar 21 '19 at 15:24
  • 1
    Well, after having faced the same issue, turns out @ADyson is right. In my case i was exporting right from a Vue Component, it returns those symbols straight to the console using Axios but if you fire the 'export' action say from a link, it works just fine. Just make sure Axios sends data to your Laravel Controller. Good luck. – LDUBBS Jun 12 '19 at 01:12

1 Answers1

3

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.

ADyson
  • 57,178
  • 14
  • 51
  • 63