donglaohua1671
2016-11-11 13:03
浏览 82

使用CodeIgniter和PHPExcel从ajax响应处理文件下载的任何方法

I am struggling with achieving what I want and am not sure if it is possible. I am using CodeIgniter and PHP for my web application. My home view allows users to query a database and the results are generated and displayed in the table form on the page. The user will then review the table and be provided the option of downloading as an xlsx Excel file. I am using an ajax post to send the table data to my PHP controller that will create the Excel file. I also need this to work in all browsers especially Safari, as the client will access the application from Ipads as well as desktop machines.

My home ajax post: (t is the id of the generated table)

$("#btnExport").click(function() {
    $.ajax({
        type: "POST",
        url: '<?php echo base_url();?>index.php/Home/excel',
        datatype: 'html',
        data: {
            'queryData': $("#t").html()},
        success: function (response) {
            alert(response);
        }             
    });
});

My controller function:

public function excel()
{
    $this->load->library('excel');
    $filename = "data";
    $table = $this->input->post('queryData');
    $objPHPExcel = new PHPExcel();
    $tmpfile = time().'.html';
    file_put_contents($tmpfile,$table);
    $objReader = PHPExcel_IOFactory::createReader('HTML');
    $objPHPExcel = $objReader->load($tmpfile);

    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment;filename='.$filename);
    header('Cache-Control: max-age=0');

    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
    $objWriter->save('php://output');       
    unlink($tmpfile);
}

The problem is the handling of the ajax response I've read its impossible to download a file from ajax. Everything I have tried is not working The response is binary encoded data I am assuming is the excel file. Is there a workaround to this problem? I decided on ajax as the table can change dynamically given the current query, and needs to be sent to the server accordingly.Thanks for any assistance.

EDIT In the linked question it is about submitting forms and not triggering a download. I am not submitting any forms, just passing an html table to the PHP to build the Excel file. I fail to see how that is relevant to my problem. Am I misunderstanding?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dongliao2011 2016-11-12 11:57
    已采纳

    Submitting a form is the best you can do to trigger a file download... It's better to create one even if you don't have a form.

    var baseUrl = '<?php echo base_url();?>'
    
    var $form = $(`<form method="post" hidden action="${baseUrl}index.php/Home/excel"><textarea name="queryData">`)
    $form.find('textarea').val($("#t").html())
    $form.appendTo('body').submit()
    

    There is however one alternative to saving ajax responses and that is by creating a link with a object url from a blob response, setting the download attribute and trigger a click (in IE you need to call navigator.saveOrOpenBlob)
    There is a good lib out there that is called FileSaver to abstract out all nasty vendor specifics

    The way you would use it is by doing this:

    fetch(url, {method: 'post', body: data})
    .then(res => {
       var cd = res.header.get('Content-Disposition')
       var filename = cd.match(/filename="(.+)"/)[1]
    
       return res.blob().then(blob => saveAs(blob, filename))
    })
    

    But it's not as good as submitting a form and getting a bit of help from a server that can send a Content-Disposition header cuz not all browser (safari mainly) supports download attribute in links...

    点赞 打赏 评论
  • dshdsh2016 2016-11-12 05:12

    there are 2 possibilities that i know

    1. store the constructed table in localStorage of your browser

    <div id="myTable">
      <table>
        <tr>
        <th>A</th>
        <th>B</th>
      </tr>
       <tr>
          <td>Value for column A</td>
          <td>Value for column B</td>
      </tr>
     </table>
    </div>
    

    // in jquery

            $(document).ready(function(){
               alert('nothing');
    
                if (typeof(Storage) !== "undefined") {
                    // Code for localStorage/sessionStorage.
    
    
    
                   var table = $('#myTable').html();
    
                  localStorage.setItem("storedTable",table);
    
    
    
                } else {
    
                    console.log('no support');
                    // Sorry! No Web Storage support..
                }
    
            });
    
    // now you can get the table in the next page like this
    
    var table = localStorage.getItem("storedTable");
    

    2. solution, store them in the $_SESSION like this

      session_start()
      $_SESSION["myTable"]  = $yourConstructedTable
    

    redirect to that page where you want to print

    get the table like so

            session_start();
     header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    
            $table =   $_SESSION["myTable"];
           unset($_SESSION["myTable"]); // don't forget to unset the session
    
        // rest of your code
    
    点赞 打赏 评论

相关推荐 更多相似问题