Як змусити завантажувати файл у бекенді WordPress?


30

Я хотів би додати кнопку «Клацнути для завантаження» до одного з моїх плагінів 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();

Це, здається, працює, але я просто хочу перевірити, чи є найкраща практика там.

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

Відповіді:


39

Якщо я правильно вас зрозумів, ви хочете мати 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();
  }
}

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

Ось як це виглядає у FireFox ( Зверніть увагу, що на екрані екрана немає /downloads/віртуальної каталоги, тому що після зйомки та анотування скріншоту просто здавалося гарною ідеєю додати '/downloads/'віртуальний каталог):

Знімок екрана URL-адреси для завантаження файлу CSV
(джерело: 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-й виклик гака проти третього дзвінка), то чому б дозволити WordPress робити більше роботи, ніж потрібно? (Я використовував плагін Instrument Hooks, щоб визначити, який гачок використовувати.)

У гачку я перевіряю, щоб переконатися, що моя 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 )Знімок екрана Завантаження файлу за URL-адресою з меню меню Інструменти адміністратора WordPress


Майк, дякую за допомогу. Єдиний замах на цю функцію полягає в тому, що я хотів би, щоб файл був завантажений з бекенда. Схоже, що template_redirect не працює на бекенді, і якщо я не повинен використовувати admin_init, мені цікаво, що я повинен використовувати замість цього. Адже admin_init, здається, працює на мене зараз, я можу притримуватися цього принаймні на короткий термін. Це незначна особливість, яку збираються використовувати лише деякі люди.
Дейв Морріс

@Dave Morris - Чи можете ви визначити, що ви маєте на увазі під "зворотним кінцем" ? Ви маєте на увазі на сервері? Якщо так, то, 'template_redirect'безумовно, працює на сервері. Якщо ні, я б зовсім заплутався; Ви можете уточнити проблему? Заздалегідь спасибі.
MikeSchinkel

@Dave: Якщо ви маєте на увазі область адміністратора "зворотним кінцем", це все одно буде працювати. URL-адреса для завантаження починається з /downloads/data.csvнеіснуючого файлу, тому "передній кінець" WordPress буде обробляти цей запит і в кінцевому підсумку дійти до нього template-redirect. Ви просто створите посилання в області адміністратора, яке вказує на цю URL-адресу фронту. (Треба сказати, що таким чином ви не отримуєте захист входу адміністратора безкоштовно - кожен, хто знає URL, може завантажити файл, але, можливо, є простий спосіб це виправити?)
Ян Фабрі

@Jan Fabry - Ах, я розумію зараз. Під "зворотним кінцем" він мав на увазі всередині адміністратора, правда? Він може використовувати функцію current_user_can()з вищевказаним кодом або використовувати інший підхід. Після цього коментаря я додам оновлення до своєї відповіді.
MikeSchinkel

Так, прошу вибачення, я не отримую сповіщення електронною поштою від цього веб-сайту, так що це пояснює мою затримку з відповіддю. Я дійсно мав на увазі адміністраторську область WordPress, коли сказав "бекенд". Вибач за це. Я спробую використовувати template_redirect і побачити, що станеться. Спасибі! ~ Дейв
Дейв Морріс

3

ще один корисний плагін для експорту в 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();

2

admin_init Гак або load- (сторінка) Гачок, здається, працює, WordPress не був встановлений заголовком у цьому стані. Я використовую гачок завантаження (сторінка), оскільки він працює під час завантаження сторінки меню адміністрації. Ви можете завантажити свій сценарій для певної сторінки.

Ви можете перевірити завантаження (на сторінці) Гачок на WordPress Codex

Якщо ви використовуєте admin_init Hook, переконайтеся, що ніколи не перевіряєте за допомогою check_admin_referer або інший скрипт, можливо, пройдіть умову, вийде файл вашого завантаження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.