2

I'm trying to generate a .json file to download using CodeIgniter's force_download() in an Ajax call, but it doesn't work as expected.

Here is my Ajax call:

$.ajax({
    url: /myfunction, 
    type: 'POST', 
    data: {value_sent: my_json_array}
});

And my PHP function:

public myfunction()
{
    $dl_array = $this->input->post("value_sent");
    $this->load->helper('download');
    force_download("file.json", $dl_array);
}

Data is sent (I double checked), but download prompt is never shown. I assume force_download() fails, but I don't understand why.

Any help is much appreciated, thanks!

SuN
  • 1,036
  • 2
  • 12
  • 25
  • is `myfunction` executed? – jny May 15 '15 at 14:22
  • yes, if I echo something instead, and use this value on callback it works. – SuN May 15 '15 at 14:27
  • what is /myfunction (maybe it should be quoted). Could you provide how your my_json_array looks – top.dev May 15 '15 at 14:28
  • 1
    ajax calls occur in the background of the browser. it's not intended for downloads, and since you have no `success` handler on the ajax call any data returned from the call is simply thrown away. – Marc B May 15 '15 at 14:28
  • Is there something to do on success to make it work? I'd like to get data from browser's localstorage and output result in a .json file. – SuN May 15 '15 at 14:33
  • myfunction it's not a JavaScript function. Your Ajax has now idea about it. You should specify `url` parameter explicitly, like `url: "/download/myfuction"`. Where `download/myfuction` is your Codeingniter controller/action – top.dev May 15 '15 at 14:34
  • 1
    You need to return the data somehow using the success function I believe you will have to force a pop up to trigger a download. – David Nguyen May 15 '15 at 14:34
  • @ top.dev thanks but url: `/myfunction` already targets my CI controller. I can send a callback value, it works. – SuN May 15 '15 at 14:39

2 Answers2

4

This isn't a problem with CodeIgniter, it's a limitation of JavaScript. You can't download files via AJAX, as referenced in Download a file by jQuery.Ajax.

you can't do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns)

Community
  • 1
  • 1
gabe3886
  • 4,235
  • 3
  • 27
  • 31
  • I know, but I'm using PHP to generate the download, not javascript. Ajax is only used because I'm taking data from localStorage. – SuN May 15 '15 at 14:30
  • 1
    You might be using PHP to generate the download, but the call to PHP is from JavaScript and via an AJAX call, which is waiting for the response from the server. As a file download isn't a server response ti expects, it fails to do anything. What you will need to do is send the data as part of a form to the CodeIgniter page and let it handle the download as a regular server request. – gabe3886 May 15 '15 at 14:32
  • you mean I should use something like `$("form#mydownload").submit();` instead? – SuN May 15 '15 at 14:35
  • Yes. once you've set variables in your form which are needed fro the download (even if they need to be hidden), then submit the form. When the user is given a download response from the server, they shouldn't be redirected once the file has downloaded. – gabe3886 May 15 '15 at 14:37
  • I replaced `$.ajax({...});` with `$('
    ').append('').appendTo('body').submit();` and it worked ;) (don't forget to add a hidden input to send your csrf token if you activated the option in your config). thx for putting me on the right track gabe3886!
    – SuN May 15 '15 at 16:52
1

Just tested it on real env.

Welcome controller (default)

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends CI_Controller {

    public function index()
    {
        $this->load->view('welcome_message');
    }

    public function myfunction()
    {
        $dl_array = $this->input->post("value_sent");
        $this->load->helper('download');
        force_download("file.json", $dl_array);
    }
}

/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */

Welcome Message View

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Welcome to CodeIgniter</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>

<script>
    $(document).ready(function () {
        $('#form').submit();
    });
</script>
<h1>Welcome</h1>

<form id="form" action="/myfunction" method="post">
    <input type="text" name="value_sent" value="text to download"/>
</form>

</body>
</html>
top.dev
  • 447
  • 1
  • 6
  • 18