idiotbaka

Serverless 函数计算 阿里云/腾讯云 PHP文件上传解决方案
前言Serverless(无服务器架构)逐渐成为了主流趋势,阿里云、腾讯云都有自己的 Serverless 产品,...
扫描右侧二维码阅读全文
25
2021/03

Serverless 函数计算 阿里云/腾讯云 PHP文件上传解决方案

前言

Serverless(无服务器架构)逐渐成为了主流趋势,阿里云、腾讯云都有自己的 Serverless 产品,函数计算和云函数的使用越来越多。而无服务器架构无法存储任何文件,PHP中也无法使用$_FILES等预定义数组,因此在传统服务器端开发中的一个简单需求,在 Serverless 中成为了个麻烦的事情。
比如场景中接收用户头像上传,然后存储到 OSS、COS、或其他存储容器中,最后返回上传结果(url)。当然,直接上传至 OSS、COS、存储容器会是更好的方式,因为阿里云和腾讯云都对 HTTP 的 Request 和 Response 的 Body 大小进行了限制(6MB)。
本文即对阿里云的函数计算以及腾讯云的云函数的文件上传提供解决方案。
QQ截图20210325145041.jpg

通用解决方案

一种通用解决方案是,客户端提交的数据是application/json格式,将文件进行base64编码后 POST 提交,函数端进行base64_decode即可。

阿里云

阿里云的解决方案比较简单,只需要解析 POST 提交为Content-Type: multipart/form-data的数据即可,这里可以直接用 ReactPHP 的 http MultipartParser类:
https://github.com/reactphp/http/blob/master/src/Io/MultipartParser.php
在代码中对该文件进行引用,然后解析 form-data 数据即可,假设 form-data 提交上来的图片 key 是 image:

function handler($request, $context): Response{
    $parsedRequest = (new MultipartParser())->parse($request);
    $file = $parsedRequest->getUploadedFiles();
    $fileImage = $file['image'];
    $fileName = $fileImage->getClientFilename();
}

然后将该文件上传至 OSS:

try {
    $ossClient = new OssClient('accessKeyId', 'accessKeySecret', 'endpoint');
    // 这里将stream进行base64编码再解码,转换为二进制数据流
    $result = $ossClient->putObject('bucket', 'object', base64_decode(base64_encode($fileImage->getStream())));
    echo $result['info']['url'];
}
catch(OssException $e) {
    echo $e->getMessage();
}

腾讯云

腾讯云的解决方式比较麻烦,云函数只对application/json的提交数据比较友好,因此需要用到API网关功能来解决。
首先在函数的触发管理中创建API网关触发的触发器:
QQ截图20210325153215.jpg
然后进入云函数的API网关面板,在服务中找到对应函数的API网关(对应云函数触发管理中的serviceId),进入网关API管理页面后,找到相应的函数。
点击进入函数,点击上方的基础设置,找到Base64编码栏,设置Base64编码为Header触发:
QQ截图20210325154150.jpg
最后,在代码端进行解析即可,base64_decode出来的数据和 form-data 的原始数据是相同的:

function main_handler($event, $context) {
    $body = json_decode($event->body, true);
    if(!$body) {
        $body = base64_decode($event->body);
    }
}

可以通过使用上文阿里云解决方案中的 form-data 解析类进行解析,
官方也提供了一篇文件上传的实践文档:https://cloud.tencent.com/document/product/583/52991

Last modification:March 25th, 2021 at 03:52 pm
本文采用 知识共享署名 4.0 国际许可协议进行许可
可自由转载、引用,但需署名作者且注明文章出处
If you think my article is useful to you, please feel free to appreciate
你也可以使用比特币或以太坊进行打赏,这样我会更开心ヾ(≧∇≦*)ゝ

Bitcoin Address: 1LqiT3NeBg9K33k7rFc3iZXrPyjECsVhNS

Ethereum Address: 0x3cd49bF3376E48ecdF2740b2868d0da682bF95ac

Leave a Comment