Как я могу принудительно загрузить файл в серверной части 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();
Кажется, это работает, но я просто хочу посмотреть, есть ли там лучшая практика.
Спасибо, Дейв
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/'
):
( источник: 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();
}
А вот скриншот активированного плагина:
( источник: mikeschinkel.com)
И, наконец, вот скриншот запуска загрузки:
( источник: mikeschinkel.com)
Еще один полезный плагин для экспорта в 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();
Admin_init Крюк или загрузка-(страница) Крюк, похоже, работает, WordPress не был установлен заголовок в этом состоянии. Я использую крючок load-(страница), потому что он запускается при загрузке страницы меню администрирования. Вы можете загрузить свой скрипт для определенной страницы.
Вы можете проверить загрузка-(страница) Крюк на кодексе WordPress
Если вы используете admin_initКрюк, убедитесь, что проверьте nonce с помощью check_admin_referer или другой сценарий, возможно, пройдет условие выведет ваш загружаемый файл.