Taro
Taro

Reputation: 1542

Joomla - Force File Download / CSV Export

I'm in need of help... this is my first time asking a question in SO, so please be kind :)

I'm trying to force-download a file from php, so when the user hits a certain button, he gets a file download. The file is a csv (email, username) of all registered users.

I decided to add this button to the admin > users screen, as you can see in this screenshotenter image description here.

So I added the following code to the addToolbar function in administrator/components/com_users/views/users/view.html.php:

JToolBarHelper::custom('users.export', 'export.png', 'export_f2.png', 'Exportar', false);

This button is mapped to the following function in the com_users\controller\users.php controller:

public function exportAllUsers() {
    ob_end_clean();
    $app = JFactory::getApplication();

    header("Content-type: text/csv");
    header("Content-Disposition: attachment; filename=ideary_users.csv");
    header("Pragma: no-cache");
    header("Expires: 0");

    echo "email,name\n";

    $model = $this->getModel("Users");
    $users = $model->getAllUsers();

    foreach ($users as $user) {
        echo $user->email . ", " . ucwords(trim($user->name)) . "\r\n";
    }

    $app->close();

}

Now, this is actually working perfectly fine.

The issue here is that after I download a file, if I hit any button in the admin that causes a POST, instead of it performing the action it should, it just downloads the file over again! For example:

I'm guessing that when I hit the export button, a JS gets called and sets a form's action attribute to an URL... and expects a response or something, and then other button's are prevented from re-setting the form's action attribute. I can't think of any real solution for this, but I'd rather avoid hacks if possible.

So, what would be the standard, elegant solution that joomla offers in this case?

Upvotes: 3

Views: 3429

Answers (2)

Mohamed Aroos
Mohamed Aroos

Reputation: 11

Add this code to your view controller

function export(){

    ob_end_clean();
    $app = JFactory::getApplication();

    header("Content-type: text/csv");
    header("Content-Disposition: attachment; filename=slic_student.csv");
    header("Pragma: no-cache");
    header("Expires: 0");

    echo "ID,School Name,Student Name,Student No\n";

    $model = $this->getModel("students");
    $users = $model->export_query();

    foreach ($users as $user) {
        echo $user->student_id . ", " . ucwords(trim($user->school_name)) . ", " . ucwords(trim($user->student_name)) . ", " . ucwords(trim($user->student_no)) . "\r\n";
    }
    $app->close();
}

Add this to the view.html.php

  JToolBarHelper::custom('students.export','','', 'CSV Export', false);

Upvotes: 1

Craig
Craig

Reputation: 9330

I think the bit you're missing is the Javascript that handles toolbar buttons, if you're just doing default actions New/Delete/Publish/Unpublish etc you don't need to add anything.

However, for custom buttons you usually have to override the default behaviour (which sets some hidden form values as they expect a page to be returned, causing a refresh and never hitting the problem you've encountered).

So normally a button relies on the submitbutton() from includes/js/joomla.javascript.js

function submitbutton(pressbutton) {
  submitform(pressbutton);
}

Which amongst other things sets the value of the task input field of the #adminForm to the buttons task, i.e. in your case user.export

You will need to add some Javascript to com_users/views/users/tmpl/default.php to call your method via window.location or similar.

As you don't want the default behaviour you need to create your own override for submitbutton() something like this:

function submitbutton(pressbutton) {
    // Check if it's your button
    if(pressbutton == 'users.export') {
        // Call your method with something like this:
        window.location = 'index.php?option=com_users&task=users.export'
        // That should be it, this way you don't set the task value for future clicks
    } else {
      // If not follow the normal path
      document.adminForm.task.value=pressbutton;
      submitform(pressbutton);
    }
}

You can find more here in the archived section of the Joomla Doc's website.

Upvotes: 2

Related Questions