创建数组转文本文件类报错:文件Resource id #11不存在
问题根源:传递了错误的参数类型
你的问题完全是代码写法的问题,和Valet环境无关——response()->download()和response()->file()要求传入的是文件路径字符串,但你的MyClass::create()方法返回的是fopen()生成的文件资源句柄(也就是报错里的"Resource id #11"),这俩根本不是一回事,框架自然找不到文件。
修正方案:让create()返回文件路径
你需要修改MyClass的逻辑,生成临时文件后返回它的路径,而不是资源句柄。这里有两种实现方式:
方式1:原生PHP函数实现
class MyClass { public static function create($props) { // 生成临时文件的完整路径 $tempFilePath = tempnam(sys_get_temp_dir(), 'prefix'); // 将数组内容写入文件 file_put_contents($tempFilePath, implode(PHP_EOL, $props)); // 注意:这里返回的是文件路径字符串,不是资源句柄 return $tempFilePath; } }
方式2:用Laravel的File Facade简化
如果你习惯用Laravel的工具类,可以这样写:
use Illuminate\Support\Facades\File; class MyClass { public static function create($props) { $tempFilePath = tempnam(sys_get_temp_dir(), 'prefix'); File::put($tempFilePath, implode(PHP_EOL, $props)); return $tempFilePath; } }
修正控制器代码
然后在控制器里,你只需要把返回的路径传给响应方法即可,还可以加上自动删除临时文件的逻辑,避免服务器堆积垃圾:
public function index() { $props = ['foo'=>'bar']; $tempFile = MyClass::create($props); // download方法:触发文件下载,第二个参数是用户看到的文件名 return response()->download($tempFile, 'my-custom-file.txt') ->deleteFileAfterSend(true); // 响应发送后自动删除临时文件 // 如果是要直接在浏览器展示文件,用file方法: // return response()->file($tempFile); }
额外说明
- 为什么
tmpfile()也不行?因为tmpfile()返回的是资源句柄,而且临时文件会在资源关闭时自动删除,当你把这个句柄传给响应方法时,文件已经被销毁了,所以会报文件不存在。 - 权限问题你不用纠结了,
sys_get_temp_dir()的权限是系统默认配置好的,Valet环境下完全没问题,之前的权限尝试没用是因为根本问题不在权限上。
内容的提问来源于stack exchange,提问作者user10547718
相关产品推荐
相关产品推荐

