PHP 如何下载文件

在日常网站开发中,用户点击按钮就能下载文件是很常见的功能——比如下载文档、图片、安装包,很多人可能不知道,这个简单的操作背后,PHP扮演了关键角色。对于新手来说,不用怕复杂的技术术语,咱们用生活化的例子一步步讲明白,PHP到底怎么实现文件下载。

先搞懂最基础的“文件读取”

很多人第一次接触PHP下载功能,其实是从“读取本地文件”开始的。就像你要从书房的书架上拿一本书,得先知道书放在哪、怎么把它拿出来。PHP里也是一样,首先要确定你要下载的文件路径——比如你网站根目录里有个叫“年度总结.pdf”的文件,路径就是./files/年度总结.pdf。

PHP 如何下载文件

举个简单的例子:如果只是想把文件内容读出来,PHP可以用readfile()函数,就像你把书的内容一页页念出来。代码大概是这样:

`php

// 先指定文件路径

$filePath = './files/年度总结.pdf';

// 检查文件存在,避免出错

if (file_exists($filePath)) {

readfile($filePath);

}

`

但这时候你会发现,浏览器只是把文件内容显示出来,根本没触发下载——就像你站在书架前直接念内容,旁边的人看不到“保存”按钮,自然没法把内容存到自己手里。这时候就需要第二个关键步骤:告诉浏览器“这是要下载的文件,不是网页内容”。

核心:告诉浏览器“这是要下载的文件”

要让浏览器弹出“保存/打开”的提示,就得设置HTTP响应头,相当于给浏览器发个明确的指令:“别把这个文件当网页显示,赶紧让用户下载存起来”。这就好比你把书递给旁边的人,说“这是给你的,请保存好”,而不是“我念给你听”。

常用的响应头有三个,咱们逐个说清楚:

第一个是Content-Type,它告诉浏览器文件的类型,比如PDF是application/pdf,图片JPG是image/jpeg,压缩包是application/zip——就像你告诉对方“这是一本书,不是一张画”。

第二个是Content-Disposition,这是最关键的指令,值设为attachment; filename="你的文件名.后缀",就是明确告诉浏览器“这是附件,请下载保存,文件名就用这个”——相当于你把文件递过去时,直接说“请下载这个叫‘年度总结.pdf’的文件”。

第三个是Content-Length,用来告诉浏览器文件的大小,这样下载进度条才能准确显示进度——就像你告诉对方“这本书有200页,你能看到读了多少”。

把这些指令结合起来,完整的PHP下载代码就出来了。比如下载刚才的PDF:

`php

$filePath = './files/年度总结.pdf';

$fileName = '年度总结.pdf';

// 检查文件是否存在

if (!file_exists($filePath)) {

die('文件不存在');

}

// 获取文件大小

$fileSize = filesize($filePath);

// 设置响应头,触发下载

header('Content-Type: application/pdf');

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

header('Content-Length: ' . $fileSize);

// 输出文件内容,完成下载

readfile($filePath);

`

处理常见的小问题

实际用的时候,很容易遇到两个小坑,咱们用例子说怎么解决:

第一个是文件名乱码。如果文件名是中文,比如“2024年度工作总结.pdf”,直接写在代码里可能会显示乱码——就像你给对方递书,名字写得模糊不清。这时候可以把文件名转成浏览器能识别的编码,比如header('Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($fileName));,就像把书名写得清晰工整,对方一眼能看懂。

第二个是大文件下载。如果文件是1G的安装包,直接用readfile()可能会卡住,就像你要搬一大箱书,一次搬不动,得分批次。这时候可以用fopen()和fread()分块读取,每次只读一部分,避免服务器内存占用过高。

这样一来,从基础的文件读取到设置响应头,再到解决常见问题,PHP实现文件下载的逻辑就清晰了——本质就是两步:先准备好要下载的文件,再给浏览器发指令让它保存文件。

上一篇 Java 原子类怎么用