Laravel 5.8 StreamDownload Перенаправление вложений файлов вместо загрузки
Я думаю, что делаю ошибку, которую не вижу в своем контроллере Laravel. У меня есть данные JSON, которые я хочу добавить в CSV, а затем загрузить этот файл в браузер.
Я отправляю форму со скрытыми входами в данные POST на сервер, выполняю запросы для данных, затем использую fputcsv() для создания обратного вызова потока файлов и возвращаю ответ Laravel Stream.
Я хочу загружать его в потоковом режиме, а не записывать файл на сервер для загрузки. Мне известны приемы использования ajax или blob для этого, но я чувствую, что форма POST для загрузки файла CSV должна быть довольно простой, а я делаю что-то глупое. Если я возвращаю только необработанные данные, строки CSV выглядят правильно, поэтому я не думаю, что это проблема с обработкой или самими данными.
ExportController
protected function csvFileHeaders($filename) {
return array(
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=". $filename,
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
);
}
public function __invoke() {
$filename = 'report_'.$endpoint.'_'.date('d-m-Y-H:i:s').'.csv';
$headers = $this->csvFileHeaders($filename);
$data = $rows->toArray();
$columns = collect(request()->input('params.columns'))->map(function($c) {
return $c['label'];
})->toArray();
$fields = collect(request()->input('params.columns'))->map(function($c) {
return $c['value'];
})->toArray();
$callback = function() use ($data, $fields, $columns) {
$file = fopen('php://output', 'rw');
fputcsv($file, $columns);
foreach($data as $d) {
// MAP values to columns OR empty strings if value is not present
fputcsv($file, collect($fields)->map(function($f) use ($d) {
if ( array_key_exists($f, $d) ) { return $d[$f]; }
return '';
})->toArray());
}
fclose($file);
};
return response()->stream($callback, $filename, $headers);
}
Форма Frontend React POST
<form id="report-export-form" action={'/report/export'} method="POST">
<div dangerouslySetInnerHTML={{ __html: csrf_token }} />
{/* BECOMES */}
{/* <div><input type="hidden" name="_token" value="...token value..."></div> */}
<input type="hidden" name="mode" value={form.mode)} />
<input type="hidden" name="endpoint" value={endpoint} />
<button className="btn btn-success" type="submit">
Export to CSV
</button>
</form>
Вместо загрузки файла происходит перенаправление страницы (обновление до исходной страницы), при этом файл не загружается. Кто-нибудь видит, какую ошибку я делаю?
Спасибо за ваше время.
1 ответ
Оказывается, была проверка правила валидатора, которая молча терпела неудачу, вызывая перенаправление.
Исправление проверки и установка заголовков Content-Type и Content-Disposition успешно загрузили вложение.
Мораль рассказа - сначала просто и не спи лишай себя.