2016-04-11 1 views
0

У меня возникли проблемы с загрузкой файлов CSV прямо в мой браузер, не сохраняя файлы где-то на моем сервере. Я нашел учебник (https://www.perpetual-beta.org/weblog/php-stream-file-direct.html), но я не могу заставить его работать!PHP - потоковое CSV-файлы для браузера

Это моя основная функция:

public function exportRecord($id) { 
    $contest = (string) $this->getContest($id); 
    $entries = (array) $this->getEntries($id); 

    $filename = sprintf('%1$s-%2$s-%3$s', str_replace(' ', '', $contest['name']), date('Ymd'), date('His')); 
    $output = fopen('php://output', 'w'); 

    ob_start(); 

    $header = array(
     'First Name', 
     'Last Name', 
     'Address', 
     'City', 
     'State', 
     'Zip', 
     'Phone', 
     'Email', 
     'Item Purchased', 
     'Partner Name', 
     'Partner #', 
     'Date Entered', 
     'Subscribe' 
    ); 

    fputcsv($output, $header); 

    foreach ($entries as $entry) { 
     fputcsv($output, $entry); 
    } 

    $string = ob_get_clean(); 

    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="' . $filename . '.csv";'); 
    header('Content-Transfer-Encoding: binary'); 

    exit($string); 
} 

Я зову следующие две функции, которые только делают запросы на моей базе данных ...

private function getContest($id) { 
    $query = sprintf(
     'SELECT name ' . 
     'FROM contests ' . 
     'WHERE id = %s;', 
     $id 
    ); 

    $result = $this->mysql->query($query); 
    $response = ''; 

    if ($result) { 
     while ($row = mysqli_fetch_assoc($result)) { 
      $response = $row; 
     } 
    } else { 
     echo $this->mysql->error; 
    } 

    return $response; 
} 

private function getEntries($id) { 
    $query = sprintf(
     'SELECT firstName, ' . 
      'lastName, ' . 
      'CONCAT(address1, ", ", address2), ' . 
      'city, ' . 
      'state, ' . 
      'zip, ' . 
      'phone, ' . 
      'email, ' . 
      'itemPurchased, ' . 
      'partnerName, ' . 
      'partnerNum, ' . 
      'dateEntered, ' . 
      'subscribe ' . 
     'FROM entries ' . 
     'WHERE contestID = %s;', 
     $id 
    ); 

    $result = $this->mysql->query($query); 
    $response = ''; 

    if ($result) { 
     while ($row = mysqli_fetch_assoc($result)) { 
      $response[] = $row; 
     } 
    } else { 
     echo $this->mysql->error; 
    } 

    return $response; 
} 

Я признателен за любую помощь/совет, который вы дам! Вот скриншот, просто чтобы дать вам представление о том, в чем проблема: Screenshot Спасибо!

+0

Какой тип браузера вы используете? Я недавно нашел проблемы с Safari с помощью этого метода. – NoobishPro

+0

Я должен был упомянуть об этом! Сожалею. Я использую последние версии Chrome и Firefox. Я также пробовал это на IE9. – brandoncluff

+0

Хорошо, еще 2 вопроса. 1) Пробовали ли вы 'error_reporting (E_ALL); ini_set ('display_errors', '1'); 'проверить, есть ли какие-либо ошибки? (поместите это вверху) - 2) вы получаете * любые * результаты вообще? Строка $ string показывает что-нибудь? Что именно не работает? – NoobishPro

ответ

1

Я закончил тем, что делал это с JS.

    } else if (action == 'export') { 
        if (result.data !== false) { 
         var data = encodeURIComponent(result.data); 
         var contest = result.contest.trim(); 
         var filename = contest + '.csv'; 
         var dataUri = 'data:text/csv;charset=utf-8,' + data; 
         var link = document.createElement('a'); 

         link.setAttribute('href', dataUri); 
         link.setAttribute('download', filename); 
         document.body.appendChild(link); 
         link.click(); 

         showMessage('Export successfully created!', 'success'); 
        } else { 
         showMessage('There are no entries for this contest! Nothing to export...', 'error'); 
        } 
       } 
0

Вам не хватает нескольких шагов от образца Джонатана Холлина. Вам нужно запустить буферизацию вывода, вам нужно записать буфер и правильно настроить заголовки. Это, возможно, потребуется некоторое изменение, но я пытался адаптировать пример к тому, что вы предоставили в этом вопросе:

<?php 
public function exportRecord($id) { 
    $contest = (array) $this->getContest($id); 
    $entries = (array) $this->getEntries($id); 

    $filename = sprintf('%1$s-%2$s-%3$s', str_replace(' ', '', $contest['name']), date('Ymd'), date('His')); 

    $header = array(
     'First Name', 
     'Last Name', 
     'Address', 
     'City', 
     'State', 
     'Zip', 
     'Phone', 
     'Email', 
     'Item Purchased', 
     'Partner Name', 
     'Partner #', 
     'Date Entered', 
     'Subscribe' 
    ); 

    export_csv($header, $entries, $filename); 
} 

private function export_csv($header, $data, $filename) { 
    // No point in creating the export file on the file-system. We'll stream 
    // it straight to the browser. Much nicer. 

    // Open the output stream 
    $fh = fopen('php://output', 'w'); 

    // Start output buffering (to capture stream contents) 
    ob_start(); 

    // CSV Header 
    if(is_array($header)){ 
     fputcsv($fh, $header); 
    } 

    // CSV Data 
    foreach ($data as $row) { 
     fputcsv($fh, $row); 
    } 

    // Get the contents of the output buffer 
    $string = ob_get_clean(); 

    // Output CSV-specific headers 
    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="' . $filename . '.csv";'); 
    header('Content-Transfer-Encoding: binary'); 

    // Stream the CSV data 
    exit($string); 
} 
+0

Спасибо за совет! Я обновил свой код и попробовал это в Chrome и Firefox ... Он по-прежнему не работает. У меня есть вывод ($ string) на моей вкладке «Сеть», когда я просматриваю страницу. Я загрузил изображение. – brandoncluff

+0

Убедитесь, что все заголовки установлены (особенно Content-Disposition & Content-Type). Я проверил это снова, и все выглядит хорошо на стороне потока сообщений csv. Похоже, вы бросаете массив в строку, и это выходит за рамки этой проблемы. Я рекомендую создать уменьшенный образец, чтобы более четко проиллюстрировать проблему. [Ссылка] https://css-tricks.com/reduced-test-cases/ – gmreburn