如何下载临时文件

时间:2013-03-13 16:18:03

标签: php

我正在尝试创建一个简短的PHP脚本,它接受一个JSON字符串,将其转换为CSV格式(使用fputcsv),并使该CSV可用作下载的.csv文件。我的想法是使用tmpfile()来担心cronjobs或磁盘空间不足,但我似乎无法让魔术发生。

这是我的尝试,这是the PHP docs of 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-DispositionContent-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);

4 个答案:

答案 0 :(得分:7)

请注意tmpfile()会返回文件句柄,但您拥有的所有函数都需要文件 path (即字符串),而不是句柄 - 尤其是basename,{ {1}}和filesize。因此,这些函数调用都不会正常工作。此外,readfile也不会返回文件扩展名。只要你想要它,即

basename

正如@Joshua Burns所说,请确保您将数组传递到'Content-Disposition: attachment; filename=data.csv' 或使用fputcsv参数。

答案 1 :(得分:3)

默认情况下,

json_decode()会将元素转换为对象而不是数组。 fputcsv()期望传递的数据是一个数组。

我建议改变:

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

要:

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

看看这是否无法解决您的问题。

在尝试解决此类问题时,我强烈建议启用display_errors并将error_reporting设置为E_ALL,以查看是否存在某些错误:< / p>

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

// Rest of your code here

答案 2 :(得分:0)

首先,检查此字符串,我会将其更改为:

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

我有一次问题,浏览器兼容性:)

答案 3 :(得分:0)

一个问题是tmpfile()会返回文件句柄,而filesize会将文件名作为参数。
以下一行:

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

可能被评估为:

header('Content-Length: 0');

检查在发生任何输出之前是否执行了对header()的所有调用。