php http发送接收文件,PHP 发送 HTTP 响应与文件下载

PHP 发送 HTTP 响应与文件下载

由 学院君 创建于9个月前, 最后更新于 7个月前

版本号 #2

1658 views

0 likes

0 collects

概述

一个完整的 HTTP 响应报文包含状态行、响应头和响应实体,关于 HTTP 响应底层结构你可以参考 HTTP 报文简介及组成结构这篇教程了解明细,这里不再重复介绍了。

在 PHP 中可以通过内置的 header 函数设置状态行及响应头,而对于响应实体,也就是我们通常看到的 API 响应数据或者 Web 页面响应视图(HTML 文档),通过 PHP 的打印函数输出即可,比如 echo、printf、var_dump 等,如果 HTML 和 PHP 脚本混合在一起,则也会解析其中的 PHP 代码,然后渲染对应的 HTML 文档作为响应实体。

耳听为虚,眼见为实,下面学院君结合常见的使用场景来演示如何在 PHP 中设置 HTTP 响应并发送给客户端。

响应状态码

我们在 http 目录下新建一个 response.php 来保存本篇教程编写的代码。默认情况下,PHP 返回的响应状态码是 200:

fe60b4c404769147c9c2969cbce7c6d3.png

比如我们只通过 echo 设置响应实体,然后在浏览器中访问 http://localhost:9000/response.php 访问这个脚本,在 Chrome 扩展台中可以看到响应状态码正是 200,这是 PHP 底层自动设置的:

3b56ab7264776826e9f09c165243e314.png

我们也可以显式在代码中设置状态码:

header('HTTP/1.1 200 OK');

echo '你好,学院君';

效果完全一致,响应状态行分三部分,第一部分是 HTTP 协议版本,第二部分是状态码,第三部分是描述状态码的短语。

除了 200 之外,还有很多其他响应状态码,比如 301、403、404、500 等,分别表征不同的含义,比如 301 表示永久重定向、403 表示没有权限、404 表示资源不存在、500 表示服务器错误。

比如说,我们设置一个 404 响应如下:

cb7bfca24a34296c3f6723294ff3d316.png

a07a3e4be69451411f8a0e4ea5ca9e4e.png

对应的响应状态行字符串格式需要和 HTTP 协议规范保持一致。合理的使用响应状态码可以对响应状态进行准确的描述,尤其是在 API 接口设计时,调用者根据响应状态码就可以大致得知错误原因。

重定向

在 PHP 中,可以通过设置 Location 响应头对用户请求进行重定向:

26ea9b5f972818eba15a832ba32c530f.png

此时当我们访问 http://localhost:9000/response.php 时,页面会重定向到 https://xueyuanjun.com:

9dde2eec9b9cf5e6f859cdafa8baa862.png

默认情况下状态码是 302,表示临时重定向,你也可以显示设置这个状态码:

header('HTTP/1.1 302 Found');

header('Location: https://xueyuanjun.com');

还有一个表示永久重定向的状态码 301,要设置 301 重定向,可以这样设置:

header('HTTP/1.1 301 Move Permanently');

header('Location: https://xueyuanjun.com');

重新在浏览器访问该脚本,可以发现重定向状态码已经变成 301 了:

8c63f5abd677c7dc9470cce715f2c91a.png

HTTP 基本认证

如果某个页面需要经过 HTTP 基本认证才能访问,可以通过设置 WWW-Authenticate 响应头来告知客户端请求用户:

69af2eb183084af11e675f0a83a481d4.png

此时访问 http://localhost:9000/response.php,就会弹出认证表单输入框:

497b85ee92db9069830be9288deec3da.png

对于这种 HTTP 基本认证中提交的用户名和密码,PHP 默认已经将它们封装到超全局变量 $_SERVER 的 PHP_AUTH_USER 和 PHP_AUTH_PW 字段中(HTTP 协议默认会通过请求头 Authorization 提交这些信息到服务端,关于相关的底层原理可以阅读 HTTP 认证实现方案介绍这篇教程)。

我们在服务端编写对应的处理代码:

// HTTP Basic 认证简单实现

if (empty($_SERVER['PHP_AUTH_USER'])) {

header('WWW-Authenticate: Basic');

} else {

$name = $_SERVER['PHP_AUTH_USER'];

$pass = $_SERVER['PHP_AUTH_PW'];

if ($name == '学院君' && $pass == '123456') {

echo '用户认证成功,可以访问该页面';

} else {

header('HTTP/1.1 401 Unauthorized');

echo '用户认证失败,请刷新页面重试';

}

}

如果用户提交的用户名或密码不正确,则返回 401 Unauthorized 状态码:

d61231632666cb64207b98f436dc8e95.png

刷新页面重试,如果认证成功,则返回如下提示信息:

800e3c27e39e904157cf8e4e5f3cd192.png

你可以在请求头中看到经过 Base64 编码加密的包含用户名和密码字段的 Authorization 字段(Basic 表示基本认证,还有 Digest 表示摘要认证,更安全一些):

9153e39c4d3e594c6dc96d3b437ce9ba.png

不过这种级别的认证等同于明文传输密码了,所以实际项目中不建议通过使用这种认证方案。

关于 PHP 设置 HTTP 响应头学院君就简单介绍到这里,已经覆盖了日常我们经常使用到的场景,当然,还有一块就是 HTTP 缓存的设置,这是一个比较宏大的话题,之前已经在 HTTP 协议详解相关教程中详细介绍过了,除非你想要系统了解 HTTP 缓存实现和性能优化,否则对初学者来说,平时也不太会用到,这里不再单独介绍,我们接下来看看响应实体设置部分。

JSON 响应

关于 Web 页面的响应实体输出(主要是 HTML 文档,或者一些调试信息输出,包括文本字符串、数组等),已经都看到过相关的演示实例了,这里我们介绍两种其他的响应输出格式,首先来看 JSON 响应。

在 API 接口中,通常返回的是 JSON 格式数据,JSON 本质上也就是对象字符串,所以在请求处理代码的最后,通过 echo 输出对应的 JSON 对象字符串即可,在 PHP 中,可以通过 PHP 内置的 json_encode 函数快速将对象、数组等格式数据转化为对应的 JSON 字符串。

我们在 http/response.php 中注释掉之前的代码,新增如下 JSON 响应代码:

// JSON 响应

$album = new stdClass();

$album->title = 'PHP 全栈工程师指南';

$album->summary = '基于 Laravel + Vue.js 框架的学习和实战,快速成为合格的 PHP 全栈开发工程师';

$album->author = '学院君';

$album->posts = [

[

'id' => 1,

'title' => 'PHP 入门指南'

],

[

'id' => 2,

'title' => 'Laravel 入门指南'

]

];

echo json_encode($album);

在浏览器中访问 http://localhost:9000/response.php,返回的 JSON 格式响应数据如下(通过 Chrome 插件 FeHelper 对 JSON 数据渲染进行了优化,这样看起来更加美观):

9d70b3aa274f90867cd40b24e35fafa0.png

非常方便。

文件下载

接下来,我们来看原生 PHP 代码中如何通过 HTTP 响应实现文件下载。其实也很简单,通过设置相关响应头,然后再通过内置的 readfile 函数读取二进制文件流通过网络输出给客户端浏览器即可。

注释掉 response.php 中的所有代码,新增如下文件下载代码:

// 文件下载

// 设置下载文件内容格式

header('Content-type: application/octet-stream');

// 设置下载文件名

header('Content-Disposition: attachment; filename="laravel.zip"');

// 读取二进制文件流返回给客户端浏览器

$filepath = __DIR__ . '/files/laravel7.zip';

readfile($filepath);

这里我们下载一个位于 Web 根目录下 files 子目录下的 laravel7.zip 文件:

43deb2a30a5f0c9bf78353613d5e57d5.png

zip 格式文件对应的 MIME 类型是 application/octet-stream(映射关系可以在这里查询:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types),我们通过 Content-Type 响应头设置即可,然后通过 Content-Disposition 设置下载到本地对应的文件名,最后读取二进制文件流返回给客户端。

在浏览器中访问 http://localhost:9000/response.php,会弹出一个下载会话框:

6067be644518469d9e90d9bb6a8466dc.png

点击右下角「存储」按钮保存,即可开始下载该文件。Windows 下也是类似:

d4ffcb4aa22b85ddd6f4eebdf96c6883.png

小结

关于 HTTP 服务器、请求和响应部分我们就简单介绍到这里,由于 HTTP 协议本身是无状态的,而在某些场景中我们希望 HTTP 请求能够「记住」用户状态,比如实现用户认证、记住记录登录状态、电商网站中加入购物车到下单支付,这些都涉及到多次请求,多个页面,但是我们希望 HTTP 请求能够识别来自同一个用户的不同请求,为此,又引入了 Cookie 和 Session 的概念。下篇教程,我们将一起来探索 Cookie 和 Session,以及基于它们实现更加安全的用户认证解决方案(相对于前面的 HTTP 基本认证)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想要使用 PHP 接收通过 AJAX 发送文件,并通过 cURL 转发文件内容,可以按照以下步骤进行操作: 1. 前端 AJAX 请求: ```javascript var fileInput = document.getElementById('fileInput'); var file = fileInput.files[0]; var formData = new FormData(); formData.append('file', file); var xhr = new XMLHttpRequest(); xhr.open('POST', 'upload.php', true); xhr.onload = function() { if (xhr.status === 200) { console.log('文件上传成功'); } else { console.log('文件上传失败'); } }; xhr.send(formData); ``` 在上面的示例中,我们使用 `FormData` 对象来创建一个表单数据,并将文件添加到表单中。然后,我们使用 `XMLHttpRequest` 对象发送 POST 请求到 `upload.php` 文件,将表单数据作为请求体发送。 2. 后端 PHP 文件(upload.php): ```php <?php // 获取上传的文件 $file = $_FILES['file']; // 构建 cURL 请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://目标地址'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, [ 'file' => new CURLFile($file['tmp_name'], $file['type'], $file['name']) ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 发送 cURL 请求 $response = curl_exec($ch); curl_close($ch); // 输出 cURL 响应 echo $response; ?> ``` 在上面的 PHP 文件中,我们首先通过 `$_FILES['file']` 获取上传的文件信息。然后,我们使用 cURL 构建一个 POST 请求,设置目标地址、请求体(包含上传的文件),以及其他必要的选项。最后,我们使用 `curl_exec()` 发送 cURL 请求,并使用 `echo` 输出 cURL 的响应。 确保将目标地址替换为你实际的目标地址。 这样,当前端通过 AJAX 发送文件时,PHP接收文件并使用 cURL 将文件内容转发到目标地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值