Bagaimana saya bisa memaksa unduhan file di backend WordPress?


30

Saya ingin menambahkan tombol "Klik untuk mengunduh" ke salah satu plugin WordPress saya, dan saya tidak yakin hook mana yang digunakan. Sejauh ini, mengaitkan 'admin_init' ke kode ini tampaknya berhasil:

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

Ini sepertinya berhasil, tetapi saya hanya ingin melihat apakah ada praktik terbaik di luar sana.

Terima kasih, Dave

Jawaban:


39

Jika saya memahami Anda dengan benar, Anda ingin memiliki URL, seperti berikut ini yang tanggapannya terhadap browser adalah konten yang Anda hasilkan, yaitu .CSVfile Anda dan tidak ada konten yang dihasilkan dari WordPress?

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

Saya pikir Anda sedang mencari 'template_redirect'kail. Anda dapat menemukan 'template_redirect'di /wp-includes/template-loader.phpmana merupakan file yang harus akrab dengan semua pengembang WordPress; itu pendek dan manis dan merutekan setiap memuat halaman non-admin jadi pastikan untuk melihatnya.

Cukup tambahkan berikut ini ke functions.phpfile tema Anda atau file lain yang Anda includemasuki 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();
  }
}

Catat tes untuk '/downloads/data.csv'URL dengan memeriksa $_SERVER['REQUEST_URI']. Perhatikan juga ditambahkan ,true,200ke header()panggilan Anda di mana Anda mengatur Content-type; ini karena WordPress akan menetapkan kode status 404 "Tidak Ditemukan" karena tidak mengenali URL. Ini tidak masalah karena truememberitahu header()untuk mengganti 404WordPress telah ditetapkan dan menggunakan kode status HTTP 200 "Oke" sebagai gantinya.

Dan inilah tampilannya di FireFox ( Perhatikan tangkapan layar tidak memiliki /downloads/direktori virtual karena setelah mengambil dan mencatat tangkapan layar itu sepertinya merupakan ide bagus untuk menambahkan '/downloads/'direktori virtual):

Cuplikan layar URL unduhan untuk file CSV
(sumber: mikeschinkel.com )

MEMPERBARUI

Jika Anda ingin unduhan ditangani dari URL yang diawali dengan /wp-admin/memberikan indikasi visual kepada pengguna bahwa itu dilindungi oleh login Anda dapat melakukannya juga; uraian satu cara berikut.

Aku dikemas ke dalam kelas saat ini, yang disebut DownloadCSV, dan untuk membuat pengguna "kemampuan" yang disebut 'download_csv'untuk 'administrator'peran (membaca tentang Peran dan Kemampuan di sini ) Anda hanya bisa dukung-dukungan off dari yang telah ditetapkan 'export'peran jika Anda suka dan jika demikian hanya mencari & mengganti 'download_csv'dengan 'export'dan hapus register_activation_hook()panggilan dan activate()fungsinya. Ngomong-ngomong, kebutuhan akan kait aktivasi adalah salah satu alasan mengapa saya memindahkan ini ke sebuah plugin daripada menyimpannya di file tema functions.php. *

Saya juga menambahkan opsi menu "Unduh CSV" dari menu "Alat" menggunakan add_submenu_page()dan menautkannya ke 'download_csv'kemampuan.

Terakhir saya memilih 'plugins_loaded'kail karena itu adalah kail paling awal yang bisa saya gunakan. Anda bisa menggunakan 'admin_init'tetapi kait itu dijalankan lebih lambat (panggilan hook ke-1130 vs panggilan ke-3) jadi mengapa membiarkan WordPress melakukan lebih banyak pekerjaan membuang-buang daripada yang seharusnya? (Saya menggunakan plugin Instrument Hooks saya untuk mencari tahu hook mana yang akan digunakan.)

Dalam kait saya memeriksa untuk memastikan URL saya mulai dengan /wp-admin/tools.phpmemeriksa $pagenowvariabel, saya memverifikasi itu current_user_can('download_csv')dan jika itu lewat maka saya menguji $_GET['download']untuk melihat apakah itu berisi data.csv; jika ya kita menjalankan kode yang sama seperti sebelumnya. Saya juga menghapus ,true,200dari panggilan ke header()dalam contoh sebelumnya karena di sini WordPress tahu itu adalah URL yang baik sehingga belum menetapkan status 404. Jadi, inilah kode Anda:

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

Dan inilah screenshot dari plugin yang diaktifkan: (sumber: mikeschinkel.com )Cuplikan layar Halaman Plugin menunjukkan plugin yang diaktifkan

Dan akhirnya inilah tangkapan layar memicu unduhan: (sumber: mikeschinkel.com )Cuplikan layar Mengunduh file dengan URL dari opsi menu Tools admin WordPress


Mike, terima kasih atas bantuannya. Satu-satunya menangkap dengan fitur ini adalah bahwa saya ingin file diunduh dari backend. Sepertinya template_redirect tidak berfungsi di backend, dan jika saya tidak seharusnya menggunakan admin_init, saya bertanya-tanya apa yang harus saya gunakan. admin_init tampaknya berfungsi untuk saya sekarang, saya mungkin tetap dengan itu setidaknya untuk jangka pendek. Ini fitur kecil yang hanya akan digunakan beberapa orang.
Dave Morris

@ Dave Morris - Bisakah Anda mendefinisikan apa yang Anda maksud dengan "back end" ? Apakah yang Anda maksud di server? Jika ya, 'template_redirect'pasti berjalan di server. Jika tidak, saya benar-benar bingung; dapatkah Anda menjelaskan masalahnya? Terima kasih sebelumnya.
MikeSchinkel

@ Dave: Jika Anda maksudkan area admin pada "back end", ini masih akan berfungsi. URL unduhan dimulai dengan /downloads/data.csv, yang merupakan file tidak ada, sehingga WordPress "ujung depan" akan menangani permintaan ini dan akhirnya mencapai template-redirect. Anda cukup membuat tautan di area admin yang mengarah ke URL bagian depan ini. (Harus dikatakan bahwa dengan cara ini, Anda tidak mendapatkan perlindungan login admin secara gratis - siapa pun yang mengetahui URL dapat mengunduh file, tetapi mungkin ada cara mudah untuk memperbaikinya?)
Jan Fabry

@ Jan Fabry - Ah, saya mengerti sekarang. Dengan "back end" yang dia maksud dari dalam admin, kan? Dia dapat menggunakan fungsi current_user_can()dengan kode di atas atau mengambil pendekatan lain. Setelah komentar ini, saya akan menambahkan pembaruan ke jawaban saya.
MikeSchinkel

Ya, saya minta maaf, saya tidak menerima peringatan email dari situs ini, jadi itu menjelaskan keterlambatan saya dalam menjawab kembali. Saya memang merujuk ke admin area WordPress ketika saya mengatakan "backend". Maaf soal itu. Saya akan mencoba menggunakan template_redirect dan melihat apa yang terjadi. Terima kasih! ~ Dave
Dave Morris

3

satu lagi plugin yang bermanfaat untuk mengekspor ke CSV. semoga bermanfaat bagi seseorang

    <?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 Hook atau load- (halaman) Hook sepertinya berfungsi, WordPress belum mengatur header dalam keadaan ini. Saya menggunakan load- (halaman) Hook karena itu berjalan ketika halaman menu administrasi dimuat. Anda dapat memuat skrip Anda untuk halaman tertentu.

Anda dapat memeriksa memuat- (halaman) Hook pada WordPress Codex

Jika Anda menggunakan admin_init Hook pastikan untuk memverifikasi nonce menggunakan check_admin_referer atau skrip lain mungkin melewati kondisi ini akan mendapatkan output file unduhan Anda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.