Подтвердить что ты не робот

Как загрузить временный файл

Я пытаюсь создать короткий PHP script, который берет строку JSON, преобразует ее в формат CSV (используя fputcsv) и делает этот CSV доступным как загруженный .csv файл. Моя мысль заключалась в том, чтобы использовать tmpfile(), чтобы не беспокоиться о cronjobs или нехватке дискового пространства, но я не могу заставить магию произойти.

Здесь моя попытка, которая представляет собой преобразованный пример из документов PHP readfile:

$tmp = tmpfile();
$jsonArray = json_decode( $_POST['json'] );
fputcsv($tmp, $jsonArray);

header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='.basename($tmp));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($tmp));

ob_clean();
flush();
readfile($tmp);

Мне кажется, что заголовки Content-Disposition и Content-Transfer-Encoding ошибочны, но я не уверен, как их исправить. Например, basename($tmp), похоже, ничего не возвращает, и я не уверен, что text/csv передается как двоичная кодировка. Аналогично, echo filesize($tmp) также пуст. Есть ли способ сделать то, что я пытаюсь здесь?

[изменить]

** Ниже приведен рабочий код, который я написал в результате принятого ответа: *

$jsonArray = json_decode( $_POST['json'], true );
$tmpName = tempnam(sys_get_temp_dir(), 'data');
$file = fopen($tmpName, 'w');

fputcsv($file, $jsonArray);
fclose($file);

header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=data.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($tmpName));

ob_clean();
flush();
readfile($tmpName);

unlink($tmpName);
4b9b3361

Ответ 1

Обратите внимание, что tmpfile() возвращает дескриптор файла, но для всех функций вам нужен путь к файлу (т.е. строка), а не дескриптор - особенно basename, filesize и readfile. Поэтому ни один из этих вызовов функций не будет работать корректно. Также basename также не будет возвращать расширение файла. Просто назовите его, как хотите, т.е.

'Content-Disposition: attachment; filename=data.csv'

Как говорит @Joshua Burns, убедитесь, что вы передаете массив в fputcsv или используете параметр assoc.

Ответ 2

json_decode() по умолчанию переводит элементы в объекты, а не в массивы. fputcsv() ожидает, что данные передаются как массив.

Я бы рекомендовал изменить:

$jsonArray = json_decode( $_POST['json'] );

To:

$jsonArray = json_decode( $_POST['json'], True );

И посмотрите, не устранит ли эта проблема.

При попытке решить такие проблемы я настоятельно рекомендую включить display_errors и установить error_reporting на E_ALL, чтобы увидеть, есть ли какая-то ошибка, которую вы пропускаете:

<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');

// Rest of your code here

Ответ 3

Во-первых, проверьте эту строку, я бы изменил ее на:

header('Content-Disposition: attachment; filename="'.basename($tmp).'"');

У меня была проблема с ним один раз с совместимостью с браузером:)

Ответ 4

Одна из проблем заключается в том, что tmpfile() возвращает дескриптор файла, а filesize принимает имя файла как параметр.
Следующая строка:

header('Content-Length: ' . filesize($tmp));

вероятно, оценивается как:

header('Content-Length: 0');

Убедитесь, что все вызовы header() выполняются до того, как произойдет какой-либо вывод.