如何下载临时文件

时间:2022-04-09 04:06:09

I'm trying to create a short PHP script that takes a JSON string, converts it to CSV format (using fputcsv), and makes that CSV available as a downloaded .csv file. My thought was to use tmpfile() to not worry about cronjobs or running out of disk space, but I can't seem to make the magic happen.

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

Here's my attempt, which is a converted example from the PHP docs of readfile:

这是我的尝试,这是来自readfile的PHP文档的转换示例:

$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);

I feel like the Content-Disposition and Content-Transfer-Encoding headers are wrong, but I'm not sure how to fix them. For example, basename($tmp) doesn't seem to return anything, and I'm not sure text/csv transfers as binary encoding. Likewise, echo filesize($tmp) is blank as well. Is there a way to do what I'm attempting here?

我觉得Content-Disposition和Content-Transfer-Encoding标头是错误的,但我不确定如何修复它们。例如,basename($ tmp)似乎没有返回任何内容,我不确定text / csv是否为二进制编码。同样,echo filesize($ tmp)也是空白的。有没有办法做我在这里尝试的事情?

[Edit]

[编辑]

**Below is the working code I wrote as a result of the accepted answer:*

**以下是我接受的答案后写的工作代码:*

$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 个解决方案

#1


6  

Note that tmpfile() returns a file handle, but all the functions you have need a file path (i.e a string), not a handle - notably basename, filesize, and readfile. So none of those function calls will work correctly. Also basename won't return a file extension either. Just call it whatever you want, i.e

请注意,tmpfile()返回一个文件句柄,但您需要的所有函数都需要一个文件路径(即字符串),而不是句柄 - 特别是basename,filesize和readfile。因此,这些函数调用都不会正常工作。 basename也不会返回文件扩展名。只要你想要它,即

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

As @Joshua Burns also says, make sure you're passing in an array to fputcsv or use the assoc parameter.

正如@Joshua Burns所说,确保你将数组传递给fputcsv或使用assoc参数。

#2


3  

json_decode() by default translates elements into objects rather than arrays. fputcsv() expects the data passed to be an array.

默认情况下,json_decode()将元素转换为对象而不是数组。 fputcsv()期望传递的数据是一个数组。

I'd recommend changing:

我建议改变:

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

To:

至:

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

And see if that doesn't fix your problem.

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

When attempting to tackle problems such as these I'd highly recommend enabling display_errors and setting error_reporting to E_ALL to see if there some sort of error you are missing out on:

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

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

// Rest of your code here

#3


0  

Firstly, check this string out, i would change it to:

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

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

i had the problem with it once, with browser compatibility :)

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

#4


0  

One problem is that tmpfile() returns a file handle, while filesize takes a filename as parameter.
The following line:

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

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

probably gets evaluated as:

可能被评估为:

header('Content-Length: 0');

Check that all the calls to header() are executed before any output happens.

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

#1


6  

Note that tmpfile() returns a file handle, but all the functions you have need a file path (i.e a string), not a handle - notably basename, filesize, and readfile. So none of those function calls will work correctly. Also basename won't return a file extension either. Just call it whatever you want, i.e

请注意,tmpfile()返回一个文件句柄,但您需要的所有函数都需要一个文件路径(即字符串),而不是句柄 - 特别是basename,filesize和readfile。因此,这些函数调用都不会正常工作。 basename也不会返回文件扩展名。只要你想要它,即

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

As @Joshua Burns also says, make sure you're passing in an array to fputcsv or use the assoc parameter.

正如@Joshua Burns所说,确保你将数组传递给fputcsv或使用assoc参数。

#2


3  

json_decode() by default translates elements into objects rather than arrays. fputcsv() expects the data passed to be an array.

默认情况下,json_decode()将元素转换为对象而不是数组。 fputcsv()期望传递的数据是一个数组。

I'd recommend changing:

我建议改变:

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

To:

至:

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

And see if that doesn't fix your problem.

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

When attempting to tackle problems such as these I'd highly recommend enabling display_errors and setting error_reporting to E_ALL to see if there some sort of error you are missing out on:

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

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

// Rest of your code here

#3


0  

Firstly, check this string out, i would change it to:

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

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

i had the problem with it once, with browser compatibility :)

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

#4


0  

One problem is that tmpfile() returns a file handle, while filesize takes a filename as parameter.
The following line:

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

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

probably gets evaluated as:

可能被评估为:

header('Content-Length: 0');

Check that all the calls to header() are executed before any output happens.

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