Download button in a plugin’s settings page

I managed to get the behaviour I was looking for with the following code :

add_action('admin_menu', 'my_plugin_menu');

function my_plugin_menu() {
    add_menu_page('Plugin management', 'Plugin management', 'manage_options', 'my_plugin-plugin-settings', 'my_plugin_settings_page', 'dashicons-admin-generic');
}


function my_plugin_settings_page() {
    if ( !current_user_can( 'manage_options' ) )  {
        wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
    }
    ?>
        <p>Please click the button below to download the file.</p>
        <form action="http://my-website-url/wp-admin/admin-post.php?action=add_foobar&data=foobarid" method="post">
          <input type="hidden" name="action" value="add_foobar">
          <input type="hidden" name="data" value="foobarid">
          <input type="submit" value="Download the file">
        </form>

    </div>
    <?php
}

// From : https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_(action)
add_action( 'admin_post_add_foobar', 'prefix_admin_add_foobar' );

function prefix_admin_add_foobar() {
    // Handle request then generate response using echo or leaving PHP and using HTML
    $filename = "file.csv";
    $array = array(array(1,2,3,4), array("merle","mésange","pie","coucou"));
    $delimiter = ",";

    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename="'.$filename.'";');

    // open the "output" stream
    // see http://www.php.net/manual/en/wrappers.php.php#refsect2-wrappers.php-unknown-unknown-unknown-descriptioq
    $f = fopen('php://output', 'w');

    foreach ($array as $line) {
        fputcsv($f, $line, $delimiter);
    }
    die();
}

The admin_post_(action) hook was very helpful.