0

I create a PHP and ajax codes to create CSV file and download it when click a button. The PHP codes work fine, and for ajax I modify and set js codes according to Handle file download from ajax post all works good. but the downloaded csv file is empty while the file in custom file is correct. I use this codes in custom wordpress plugin.

function _exe_export_vendor_products(){
 $current_user_id = esc_sql($_POST['c_user_id']);
 $arg = array(
 'limit' => 20,
 'author'    => $current_user_id
);
$product_list = wc_get_products($arg);

$title_array[] = array('ID', 'name', 'Price', 'SalePrice');

foreach($product_list as $_list){
$data_array[] = array($_list->get_id(), $_list->get_name(), $_list->get_price(), $_list->get_sale_price());
}
$final_array = array_merge($title_array, $data_array);

date_default_timezone_set("Asia/Tehran");
$current_date = date('Y-m-d-H-i');
$filename = "export-" . $current_user_id . "-" . $current_date . ".csv";
$f = fopen('https://sitename.com/export-import/' . $filename, 'w');
$delimiter=";";
foreach($final_array as $final_item){
  fputcsv($f, $final_item, $delimiter);
}
fseek($f, 0);
header('Content-Type: text/csv; charset=UTF-8' );
header('Content-Encoding: UTF-8');
header('Content-Disposition: attachment; filename="'.$filename.'";');
readfile($filename);
fclose($f);
}

and JS codes:

jQuery.ajax({
type: "POST",
url: Ajax_object_dokan.ajax_url,
data:{
    action: '_dokan_export_vendor',
    c_user_id : current_user_id
},
xhrFields:{
    responseType: 'blob'
},
success: function(blob, status, xhr){
    var filename = "";
    var disposition = xhr.getResponseHeader('Content-Disposition');
    if(disposition && disposition.indexOf('attachment') !== -1){
        var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        var matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
    }
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
        window.navigator.msSaveBlob(blob, filename);
    } else {
        var URL = window.URL || window.webkitURL;
        var downloadUrl = URL.createObjectURL(blob);

        if (filename) {
            var a = document.createElement("a");
            // safari doesn't support this yet
            if (typeof a.download === 'undefined') {
                window.location.href = downloadUrl;
            } else {
                a.href = downloadUrl;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
            }
        } else {
            window.location.href = downloadUrl;
        }

        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
    }
    
}
});

I create file in https://sitename.com/export-import/filename.csv while the create tag a in JS has link to https://sitename.com/59360c8b-22a5-462b-9d7e-240e54a0c094.

How can I access to correct link to download file with ajax?

Olivier
  • 13,283
  • 1
  • 8
  • 24
Web Design
  • 77
  • 2
  • 19

1 Answers1

1

There are several issues in your code:

  • You use fopen() to access a URL with w mode. It can't work. You can only access a URL for reading. Just use a path on the filesystem, for example:
$f = fopen($_SERVER['DOCUMENT_ROOT'] . '/export-import/' . $filename, 'w');
  • You call readfile() with just the file name, not the full path.

  • You call readfile() on the file before closing it. It may work but it's better to call fclose() first. And you don't need to call fseek().

  • You set the Content-Encoding: UTF-8 header. That header is used to indicate compression (e.g. gzip), not the character encoding. Remove it.

Also note that you don't need AJAX to download a file. You can just submit a form. All that complicated JS code is unnecessary.

Olivier
  • 13,283
  • 1
  • 8
  • 24