Как я могу принудительно загрузить файл в серверной части WordPress?


Я хотел бы добавить кнопку "Нажмите, чтобы загрузить" в один из моих плагинов WordPress, и я не уверен, какой крючок использовать. До сих пор подключение 'admin_init' к этому коду, похоже, работает:

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

Кажется, это работает, но я просто хочу посмотреть, есть ли там лучшая практика.

Спасибо, Дейв

 33
Author: Dave Morris, 2010-10-31

3 answers

Если я правильно вас понял, вы хотите иметь URL-адрес примерно следующего вида , чьим ответом браузеру будет создаваемый вами контент, т.Е. Ваш .CSV файл и никакого сгенерированного контента из WordPress?

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

Я думаю, что вы ищете крючок 'template_redirect'. Вы можете найти 'template_redirect' в /wp-includes/template-loader.php, с которым должны ознакомиться все разработчики WordPress; он короткий и приятный и перенаправляет каждую загрузку страницы, не являющуюся администратором, поэтому не забудьте взглянуть на это.

Просто добавьте следующее в файл вашей темы functions.php или в другой файл, в котором вы include 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();
  }
}

Обратите внимание на проверку URL-адреса '/downloads/data.csv', проверив $_SERVER['REQUEST_URI']. Также обратите внимание на добавленный ,true,200 в ваш вызов header(), где вы установили Content-type; это связано с тем, что WordPress установит 404 " Не найден" код состояния, потому что он не распознает URL-адрес. Это не проблема, хотя, как true говорит header() заменить 404, установленный WordPress, и использовать HTTP 200 "Хорошо" вместо этого код состояния.

И вот как это выглядит в FireFox ( Примечание на снимке экрана нет виртуального каталога /downloads/, потому что после создания и аннотирования снимка экрана просто показалось хорошей идеей добавить виртуальный каталог '/downloads/'):

Screenshot of a download URL for a CSV file
( источник: mikeschinkel.com)

ОБНОВЛЕНИЕ

Если вы хотите, чтобы загрузка обрабатывалась с URL-адреса с префиксом /wp-admin/, чтобы дайте пользователю визуальное указание на то, что он защищен логином, вы также можете это сделать; ниже приводится описание одного из способов.

На этот раз я инкапсулировался в класс под названием DownloadCSV и создал пользователя "возможности" под названием 'download_csv' для роли 'administrator' (читайте о ролях и возможностях здесь) Вы можете просто отказаться от предопределенной роли 'export', если хотите, и если да, просто найдите и замените 'download_csv' на 'export' и удалите register_activation_hook() вызов и функция activate(). Кстати, необходимость в крючке активации является одной из причин, по которой я перенес это в плагин вместо того, чтобы хранить в файле темы functions.php.*

Я также добавил опцию меню "Загрузить CSV" из меню "Инструменты" с помощью add_submenu_page() и связал ее с возможностью 'download_csv'.

Наконец, я выбрал крючок 'plugins_loaded', потому что это был самый ранний подходящий крючок, который я мог использовать. Вы могли бы использовать 'admin_init', но этот крючок запускается намного позже (1130-й вызов крючка против 3-й вызов крючка) так зачем же позволять WordPress выполнять больше ненужной работы, чем нужно? (Я использовал свой плагин Инструментальные крючки, чтобы выяснить, какой крючок использовать.)

В крючке я проверяю, чтобы мой URL начинался с /wp-admin/tools.php, проверяя переменную $pagenow, я проверяю, что current_user_can('download_csv'), и если это проходит, я проверяю $_GET['download'], чтобы увидеть, содержит ли он data.csv; если да, мы запускаем практически тот же код, что и раньше. Я также удаляю ,true,200 из вызова header() в предыдущем примере, потому что здесь WordPress знает, что это хороший URL, поэтому еще не установил статус 404. Итак, вот ваш код:

<?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();
}

А вот скриншот активированного плагина: Screenshot of Plugin Page showing an activated plugin
( источник: mikeschinkel.com)

И, наконец, вот скриншот запуска загрузки: Screenshot of Downloading a file by URL from an option of the WordPress admin's Tools menu
( источник: mikeschinkel.com)

 43
Author: MikeSchinkel, 2020-06-15 08:21:38

Еще один полезный плагин для экспорта в CSV. может быть кому-то полезен

    <?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();
 4
Author: Developer, 2013-01-04 16:26:38

Admin_init Крюк или загрузка-(страница) Крюк, похоже, работает, WordPress не был установлен заголовок в этом состоянии. Я использую крючок load-(страница), потому что он запускается при загрузке страницы меню администрирования. Вы можете загрузить свой скрипт для определенной страницы.

Вы можете проверить загрузка-(страница) Крюк на кодексе WordPress

Если вы используете admin_initКрюк, убедитесь, что проверьте nonce с помощью check_admin_referer или другой сценарий, возможно, пройдет условие выведет ваш загружаемый файл.

 3
Author: Joko Wandiro, 2014-12-24 07:54:38