Axios 请求 - 来自 PHP API 的 Gzip 数据
Posted
技术标签:
【中文标题】Axios 请求 - 来自 PHP API 的 Gzip 数据【英文标题】:Axios Request - Gzip data from PHP API 【发布时间】:2019-09-22 19:38:55 【问题描述】:是否可以在 php 中 gzcompress 数据然后让 Axios 请求它?
我试过这样做,但一直收到此错误:“格式错误的 UTF-8 字符,可能编码不正确。”
我的 Axios 请求如下所示:
axios(
method: 'get',
url: 'https://someapi.com/api/test',
data: ,
config: headers: 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip'
)
.then(response =>
response.data.forEach(el =>
this.transactions.push(JSON.parse(el));
this.transactionsFull = this.transactions;
);
this.loading = false;
console.log(this.transactions);
)
.catch(e =>
this.errors.push(e)
)
$result = openssl_decrypt($cipher_text, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $auth_tag);
$json = json_decode($result);
$channel = Channel::where('uuid', $json->payload->authentication->entityId)->first();
$gzencode = gzencode(json_encode(array('transaction' => $json, 'relation' => json_decode($channel))), 8);
Redis::lpush('transactions_gzencode', $gzencode);
$length = 0;
$transactions = Redis::lrange('transactions_gzencode', 0, -1);
foreach($transactions as $item)
$length += strlen($item);
header('Content-Encoding: gzip');
header('Content-Type: application/json');
header('Content-Length: ' . $length);
return $transactions;
【问题讨论】:
您确定要完全在 PHP 中执行此操作吗?通常,它是通过适当的设置(nginx 或 Apache)在 Web 服务器端完成的。 嗨@Ruslan 但是发送压缩的数据因为它的大小更小然后解压缩它是否有意义? 你说的是对的。但是 PHP 和 Web 服务器之间没有实际的“流量”。因此,使用 PHP 压缩数据没有任何好处(也许有一些例外,但不确定它是否适用于对 REST API 的常规 JS 查询)。您可以尝试这样的操作 - php.net/manual/ru/function.gzcompress.php,但如果您在 Web 服务器级别进行压缩,您还可以控制静态资产(JS、CSS、html、图像)的 gzip,并在一处管理您的压缩策略。跨度> gzcompress 正是我正在做的。我正在做的是压缩大型 JSON 对象并将它们放入 Redis。然后我从 Redis 中检索所有内容并将其发送到我的 VueJS 前端应用程序。我遇到的问题是 Axios 没有解压缩数据。 【参考方案1】:我相信 axios 是无法解压 gzip 的,但是浏览器应该可以在 axios 接触到响应之前做到。但要让浏览器这样做,您必须使用正确的 http 标头和格式进行响应。
请注意,根据 php 文档,要在 http 响应正文中使用压缩数据,您必须使用 gzencode,而不是 gzcompress。
示例 PHP:
$compressed = gzencode(json_encode(['test' => 123]));
header('Content-Type: application/json');
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($compressed));
echo $compressed;
示例 JS:
console.log(await (await fetch('/test')).json());
// test: 123
编辑
由于您要做的是发送一组单独压缩的项目,因此您可以在 JSON 编码的 base64 编码二进制压缩数据数组中输出数据。
使用pako.js解压服务端返回的压缩事务数组的示例:
PHP:
$transactions = ['first', 'second', 'third'];
echo json_encode(array_map('base64_encode', array_map('gzencode', $transactions)));
JS:
(async () =>
const transactions = (await (await fetch('/test')).json())
.map(atob)
.map(blob => pako.inflate(blob, to: 'string' ));
console.log(transactions);
)();
请注意,现在我没有包含标头,因为我只是发送一个常规的 json 编码数组。
这种方法的缺点是压缩数据不会有太多好处,因为它会在发送到客户端之前转换为 base64。必须编码为base64,否则json_encode会尝试将二进制数据作为字符串处理,会导致字符串编码错误。
您仍然可以在发送到客户端之前压缩生成的 json 编码字符串,就像我之前的回答一样,但我不确定压缩是否仍然足够好:
$compressedTransactions = array_map('gzencode', ['first', 'second', 'third']);
$compressed = gzencode(json_encode(array_map('base64_encode', $compressedTransactions)));
header('Content-Type: application/json');
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($compressed));
echo $compressed;
【讨论】:
谢谢伙计,我现在试试这个然后回来。 strlen 不适用于压缩数据。我得到这个错误,strlen() 期望参数 1 是字符串,给定数组。 @Dally,你能写一些你的 php 代码来回答这个问题吗?好像还有什么问题,因为gzencode的返回类型是string
:php.net/manual/en/function.gzencode.php。
我写了一个小测试,能够通过 AJAX 请求数据。我更新了答案中的示例。
我为我原来的问题伙伴添加了更多代码。是不是因为我有一个多维数组?以上是关于Axios 请求 - 来自 PHP API 的 Gzip 数据的主要内容,如果未能解决你的问题,请参考以下文章
无法使用来自axios请求的request.form在flask api中获取请求正文[重复]
对 PHP API 的 Axios GET 请求不适用于自定义标头
PHP Session ID / Session 变量值随着来自 react axios / ajax 调用的每个请求而变化