本文最后更新于 2024-08-29,文章内容可能已经过时。

Alist/S3/阿里ossz制作随机图片api

本教程采用php作为基础框架,实现通过对象存储随机返回图像从事实现

  • AWS S3 协议
  • 阿里云OSS
  • .....(等待开发)

目录结构

/auto-pic-api
    ├── index.php  		#入口文件
    ├── vendor/    		#sdk文件
    ├── error.php		#异常报错
    ├── config.php		#配置文件
    ├── backend.php		#主程序脚本
    ├── composer.lock
    └── composer.json

index.php

<?php include 'backend.php';

config.php中配置文件

根据注解提示更改相应内容

<?php

return [
    'storageType' => 1, // 1 表示使用 S3,2 表示使用 OSS
    'checkDevice' => false,

    's3Config' => [
        'bucketName' => 'your-s3-bucket-name', // S3存储桶的名称
        'region' => 'auto', // S3存储桶所在的AWS区域,默认为'auto',例如'us-east-1'
        'endpoint' => '访问ip/域名', // 自定义的S3兼容服务的endpoint
        'accessKeyId' => 'your-aws-access-key-id', // AWS访问密钥ID,用于鉴权
        'accessKeySecret' => 'your-aws-secret-access-key', // AWS访问密钥Secret,用于鉴权
    ],

    'ossConfig' => [
        'bucketName' => 'your-oss-bucket-name', // 阿里云OSS存储桶的名称
        'endpoint' => 'oss-your-region.aliyuncs.com', // 阿里云OSS服务的节点(Endpoint),例如'oss-cn-beijing.aliyuncs.com'
        'accessKeyId' => 'your-aliyun-access-key-id', // 阿里云访问密钥ID,用于鉴权
        'accessKeySecret' => 'your-aliyun-access-key-secret', // 阿里云访问密钥Secret,用于鉴权
    ],
];

backend.php程序文件

注:这一部分没有代码经验的不推荐自行更改

<?php

require __DIR__ . '/vendor/autoload.php';

// 从 config.php 读取配置
$config = require __DIR__ . '/config.php';

use OSS\OssClient;
use OSS\Core\OssException;
use Aws\S3\S3Client;
use Aws\Exception\AwsException;

// 提取配置项
$storageType = $config['storageType'];  // 读取存储类型,1 表示 S3,2 表示 OSS
$checkDevice = $config['checkDevice'];  // 是否根据设备类型选择不同的图片前缀
$s3Config = $config['s3Config'];  // S3 配置
$ossConfig = $config['ossConfig'];  // OSS 配置

// 根据设备类型选择图片前缀
$imagePrefix = '';
if ($checkDevice) {
    $imagePrefix = isMobile() ? '/mobile' : '/desktop';
}

// 判断当前设备是否为移动设备
function isMobile()
{
    return preg_match('/(android|iphone|ipad|mobile)/i', $_SERVER['HTTP_USER_AGENT']);
}

// 根据存储类型获取随机图片
function fetchImage($storageType, $s3Config, $ossConfig, $imagePrefix)
{
    if ($storageType == 1) {  // 如果 storageType 为 1,则使用 S3
        // 提取 S3 配置信息
        $bucketName = $s3Config['bucketName'];
        $region = $s3Config['region'];
        $accessKeyId = $s3Config['accessKeyId'];
        $accessKeySecret = $s3Config['accessKeySecret'];

        try {
            // 创建 S3 客户端实例
            $s3Client = new S3Client([
                'region' => $region,
                'version' => 'latest',
                'endpoint' => $s3Config['endpoint'],
                'use_path_style_endpoint' => true,
                'credentials' => [
                    'key' => $accessKeyId,
                    'secret' => $accessKeySecret,
                ],
                'use_aws_shared_config_files' => false,
            ]);
        } catch (AwsException $e) {
            return ["error" => "AWS S3 Error: " . $e->getMessage()];  // 捕获 AWS S3 相关错误
        } catch (Exception $e) {
            return ["error" => "General Error: " . $e->getMessage()];  // 捕获其他一般错误
        }

        try {
            // 列出 S3 存储桶中的对象
            $result = $s3Client->listObjectsV2([
                'Bucket' => $bucketName,
                'Prefix' => $imagePrefix,
            ]);

            $images = [];
            $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];  // 允许的图片扩展名

            if (isset($result['Contents'])) {
                foreach ($result['Contents'] as $object) {
                    $key = $object['Key'];
                    $extension = strtolower(pathinfo($key, PATHINFO_EXTENSION));

                    if (in_array($extension, $allowedExtensions)) {  // 过滤出图片文件
                        $images[] = $key;
                    }
                }
            }

            if (empty($images)) {
                return ["error" => "No image files found in the S3 bucket."];  // 如果没有找到图片,返回错误
            }

            // 随机选择一张图片
            $randomImage = $images[array_rand($images)];
            $object = $s3Client->getObject([
                'Bucket' => $bucketName,
                'Key' => $randomImage,
            ]);

            return ["contentType" => $object['ContentType'], "body" => $object['Body']];  // 返回图片的 MIME 类型和内容

        } catch (AwsException $e) {
            return ["error" => "AWS S3 ListObjects Error: " . $e->getMessage()];  // 捕获 AWS S3 列出对象相关错误
        } catch (Exception $e) {
            return ["error" => "General Error: " . $e->getMessage()];  // 捕获其他一般错误
        }
    } elseif ($storageType == 2) {  // 如果 storageType 为 2,则使用 OSS
        // 提取 OSS 配置信息
        $bucketName = $ossConfig['bucketName'];
        $endpoint = $ossConfig['endpoint'];
        $accessKeyId = $ossConfig['accessKeyId'];
        $accessKeySecret = $ossConfig['accessKeySecret'];

        try {
            // 创建 OSS 客户端实例
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
        } catch (OssException $e) {
            return ["error" => "OSS Error: " . $e->getMessage()];  // 捕获 OSS 相关错误
        } catch (Exception $e) {
            return ["error" => "General Error: " . $e->getMessage()];  // 捕获其他一般错误
        }

        try {
            // 列出 OSS 存储桶中的对象
            $listObjectInfo = $ossClient->listObjects($bucketName, [
                'prefix' => $imagePrefix,
            ]);

            $images = [];
            $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];  // 允许的图片扩展名

            if ($listObjectInfo->getObjectList()) {
                foreach ($listObjectInfo->getObjectList() as $objectInfo) {
                    $key = $objectInfo->getKey();
                    $extension = strtolower(pathinfo($key, PATHINFO_EXTENSION));

                    if (in_array($extension, $allowedExtensions)) {  // 过滤出图片文件
                        $images[] = $key;
                    }
                }
            }

            if (empty($images)) {
                return ["error" => "No image files found in the OSS bucket."];  // 如果没有找到图片,返回错误
            }

            // 随机选择一张图片
            $randomImage = $images[array_rand($images)];
            $object = $ossClient->getObject($bucketName, $randomImage);

            return ["contentType" => $ossClient->getObjectMeta($bucketName, $randomImage)['content-type'], "body" => $object];  // 返回图片的 MIME 类型和内容

        } catch (OssException $e) {
            return ["error" => "OSS ListObjects Error: " . $e->getMessage()];  // 捕获 OSS 列出对象相关错误
        } catch (Exception $e) {
            return ["error" => "General Error: " . $e->getMessage()];  // 捕获其他一般错误
        }
    }
}

// 获取随机图片的数据
$imageData = fetchImage($storageType, $s3Config, $ossConfig, $imagePrefix);

// 如果发生错误,显示错误信息
if (isset($imageData['error'])) {
    displayMessage($imageData['error']);
} else {
    // 输出图片的 MIME 类型和内容
    header('Content-Type: ' . $imageData['contentType']);
    echo $imageData['body'];
}

// 显示错误信息的方法
function displayMessage($message)
{
    require_once 'error.php';
}

composer.json

这一部分就是使用composer来安装AWS S3以及阿里OSS的SDK配置文件

{
    "require": {
        "aws/aws-sdk-php": "^3.0",
        "aliyuncs/oss-sdk-php": "^2.0"
    }
}

完成上述文件创建,我们就可以正式开始进入搭建了

本教程使用Alist中的S3协议进行搭建对接的123云盘

1,先进入Alist的官网安装并运行,由于网络上此教程太多,我这边不过多教学,官网的一键安装也十分方便(Alist官网地址:alist.nn.ci

2,进入Alist后台->存储->添加 来添加存储,我们以123pan为例

image-20240829180949416

3,成功添加

image-20240829181029527

4,进入123盘,在根目录新建desktop以及mobile文件夹用于存储手机和电脑访问时候呈现出不同尺寸的图片,并且检查是否正常创建

image-20240829181235977

5,进入Alist后台创建S3协议的密钥以及id

在设置->对象存储中点击S3 generate来创建Key,在下方添加桶以及位置

image-20240829181626581

配置完成后去Alist的配置文件位置修改配置文件让他启用S3服务

image-20240829182645804

6,将源码放到带有nginxphp8.0以上的web服务器中

首先我们需要安装对应的sdk,我们需要安装composer程序,然后在文件目录运行

composer install

安装完成之后修改config.php中的配置文件

注意这里的endpoint需要带上端口!

image-20240829182224121

此时我们访问网站即可正常看到图片

image-20240829182756864