web-dev-qa-db-fra.com

Comment puis-je forcer le téléchargement d'un fichier dans le backend WordPress?

J'aimerais ajouter un bouton "Cliquez pour télécharger" sur l'un de mes plugins WordPress, et je ne suis pas sûr du hook à utiliser. Jusqu’à présent, lier 'admin_init' à ce code semble fonctionner:

 header("Content-type: application/x-msdownload");
 header("Content-Disposition: attachment; filename=data.csv");
 header("Pragma: no-cache");
 header("Expires: 0");
 echo 'data';
 exit();

Cela semble fonctionner, mais je veux juste voir s'il existe une meilleure pratique.

Merci Dave

29
Dave Morris

Si je vous ai bien compris, vous voulez avoir une URL du même type / dont le navigateur répondra au contenu que vous générez, c’est-à-dire votre fichier .CSV et aucun contenu généré à partir de WordPress?

http://example.com/download/data.csv

Je pense que vous recherchez le hook 'template_redirect'. Vous pouvez trouver 'template_redirect' dans /wp-includes/template-loader.php, un fichier avec lequel les développeurs WordPress devraient se familiariser; il est court et agréable et dirige chaque chargement de page non-administrateur, alors jetez-y un coup d'œil.

Ajoutez simplement ce qui suit au fichier functions.php de votre thème ou dans un autre fichier dans lequel vous include dans functions.php:

add_action('template_redirect','yoursite_template_redirect');
function yoursite_template_redirect() {
  if ($_SERVER['REQUEST_URI']=='/downloads/data.csv') {
    header("Content-type: application/x-msdownload",true,200);
    header("Content-Disposition: attachment; filename=data.csv");
    header("Pragma: no-cache");
    header("Expires: 0");
    echo 'data';
    exit();
  }
}

Notez le test pour l'URL '/downloads/data.csv' en inspectant $_SERVER['REQUEST_URI']. Notez également le ,true,200 ajouté à votre appel header() où vous définissez le Content-type; En effet, WordPress aura défini le code d'état 404"Introuvable"} _ _ car il ne reconnaît pas l'URL. Ce n'est pas un problème cependant puisque la true indique à header() de remplacer le 404 défini par WordPress et d'utiliser le code HTTP 200"OK" à la place.

Et voici à quoi cela ressemble dans FireFox ( Remarque la capture d'écran ne possède pas de répertoire virtuel /downloads/ car après avoir pris et annoté la capture d'écran, il semblait simplement judicieux d'ajouter un répertoire virtuel '/downloads/'). :

 Screenshot of a download URL for a CSV file 
(source: mikeschinkel.com )

METTRE À JOUR

Si vous souhaitez que le téléchargement soit géré à partir d'une URL avec le préfixe /wp-admin/ pour donner à l'utilisateur une indication visuelle qu'il est protégé par un identifiant, vous pouvez également le faire; la description d'une manière suit.

J'ai encapsulé cette fois dans une classe appelée DownloadCSV et créé un utilisateur "possibilité" appelé 'download_csv' pour le rôle 'administrator'(à propos des rôles et des capacités ici ) Vous pouvez simplement utiliser le rôle 'export' prédéfini si vous le souhaitez. Dans ce cas, il suffit de rechercher & remplacer 'download_csv' avec 'export' et de supprimer l'appel register_activation_hook() et la fonction activate(). Soit dit en passant, la nécessité d'un raccordement d'activation est l'une des raisons pour lesquelles je l'ai déplacé dans un plugin au lieu de conserver le fichier functions.php du thème. *

J'ai également ajouté une option de menu "Télécharger CSV" du menu "Outils" à l'aide de add_submenu_page() et l'a liée à la fonctionnalité 'download_csv'.

Enfin, j’ai choisi le crochet 'plugins_loaded' car c’était le premier crochet approprié que je pouvais utiliser. Vous pouvez utiliser 'admin_init' mais ce hook est exécuté beaucoup plus tard (1130ème appel de hook par rapport au troisième appel de hook), alors pourquoi laisser WordPress faire plus de travail que nécessaire? (J'ai utilisé mon plugin Instrument Hooks pour déterminer quel hook utiliser.)}

Dans le crochet, je vérifie que mon URL commence par /wp-admin/tools.php en inspectant la variable $pagenow, je vérifie que current_user_can('download_csv') et si cela réussit, je teste $_GET['download'] pour voir si elle contient data.csv; Si oui, nous utilisons pratiquement le même code que précédemment. J'ai également supprimé le ,true,200 de l'appel à header() dans l'exemple précédent, car ici WordPress sait que c'est une bonne URL et n'a donc pas encore défini le statut 404. Alors voici votre code:

<?php
/*
Plugin Name: Download CSV
Author: Mike Schinkel
Author URI: http://mikeschinkel.com
 */
if (!class_exists('DownloadCSV')) {
  class DownloadCSV {
    static function on_load() {
      add_action('plugins_loaded',array(__CLASS__,'plugins_loaded'));
      add_action('admin_menu',array(__CLASS__,'admin_menu'));
      register_activation_hook(__FILE__,array(__CLASS__,'activate'));
    }
    static function activate() {
      $role = get_role('administrator');
      $role->add_cap('download_csv');
    }
    static function admin_menu() {
      add_submenu_page('tools.php',    // Parent Menu
        'Download CSV',                // Page Title
        'Download CSV',                // Menu Option Label
        'download_csv',                // Capability
        'tools.php?download=data.csv');// Option URL relative to /wp-admin/
    }
    static function plugins_loaded() {
      global $pagenow;
      if ($pagenow=='tools.php' && 
          current_user_can('download_csv') && 
          isset($_GET['download'])  && 
          $_GET['download']=='data.csv') {
        header("Content-type: application/x-msdownload");
        header("Content-Disposition: attachment; filename=data.csv");
        header("Pragma: no-cache");
        header("Expires: 0");
        echo 'data';
        exit();
      }
    }
  }
  DownloadCSV::on_load();
}

Et voici une capture d'écran du plugin activé:  Screenshot of Plugin Page showing an activated plugin 
(source: mikeschinkel.com )

Et enfin, voici une capture d'écran du déclenchement du téléchargement:  Screenshot of Downloading a file by URL from an option of the WordPress admin's Tools menu 
(source: mikeschinkel.com )

38
MikeSchinkel

encore un plugin utile pour exporter en CSV. peut être utile à quelqu'un

    <?php

class CSVExport
{
/**
* Constructor
*/
public function __construct()
{
if(isset($_GET['download_report']))
{
$csv = $this->generate_csv();

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"report.csv\";" );
header("Content-Transfer-Encoding: binary");

echo $csv;
exit;
}

// Add extra menu items for admins
add_action('admin_menu', array($this, 'admin_menu'));

// Create end-points
add_filter('query_vars', array($this, 'query_vars'));
add_action('parse_request', array($this, 'parse_request'));
}

/**
* Add extra menu items for admins
*/
public function admin_menu()
{
add_menu_page('Download Report', 'Download Report', 'manage_options', 'download_report', array($this, 'download_report'));
}

/**
* Allow for custom query variables
*/
public function query_vars($query_vars)
{
$query_vars[] = 'download_report';
return $query_vars;
}

/**
* Parse the request
*/
public function parse_request(&$wp)
{
if(array_key_exists('download_report', $wp->query_vars))
{
$this->download_report();
exit;
}
}

/**
* Download report
*/
public function download_report()
{
echo '<div class="wrap">';
echo '<div id="icon-tools" class="icon32">
</div>';
echo '<h2>Download Report</h2>';
//$url = site_url();

echo '<p>Export the Users';
}

/**
* Converting data to CSV
*/
public function generate_csv()
{
$csv_output = '';
$table = 'users';

$result = mysql_query("SHOW COLUMNS FROM ".$table."");

$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output = $csv_output . $row['Field'].",";
$i++;
}
}
$csv_output .= "\n";

$values = mysql_query("SELECT * FROM ".$table."");
while ($rowr = mysql_fetch_row($values)) {
for ($j=0;$j<$i;$j++) {
$csv_output .= $rowr[$j].",";
}
$csv_output .= "\n";
}

return $csv_output;
}
}

// Instantiate a singleton of this plugin
$csvExport = new CSVExport();
3
Developer

admin_init Hook ou load- (page) Hook semble fonctionner, WordPress n'a pas été défini d'en-tête dans cet état. J'utilise load- (page) Hook car il s'exécute lorsqu'une page de menu d'administration est chargée. Vous pouvez charger votre script pour une page spécifique.

Vous pouvez vérifier charger- (page) Hook sur WordPress Codex

Si vous utilisez admin_init Hook, assurez-vous de verify nonce utilisez check_admin_referer ou un autre script. La condition peut éventuellement renvoyer votre fichier téléchargé.

2
Joko Wandiro