21、Hyperf 3 快速使用 - Hyperf 3 上传文件 or 图片到七牛云

作者: 温新

分类: 【Hyperf 3 基础系列】

阅读: 402

时间: 2023-04-25 15:14:52

hi,我是温新,一名 PHPer

Hypref 版本:Hyperf 3.0

学习目标:掌握上传文件 or 图片到七牛云

本篇文章学习的是将文件上传到七牛云。在此之前需要准备好七牛云的对象存储空间。

准备工作

第一步:安装组件

composer require hyperf/filesystem
composer require "overtrue/flysystem-qiniu:^3.0"

第二步:生成配置文件

php bin/hyperf.php vendor:publish hyperf/filesystem

该命令会在 config/autoload 目录下生成 file.php 文件,其中关于七牛云的配置如下:

<?php

'qiniu' => [
    'driver' => \Hyperf\Filesystem\Adapter\QiniuAdapterFactory::class,
    'accessKey' => env('QINIU_ACCESS_KEY'),
    'secretKey' => env('QINIU_SECRET_KEY'),
    'bucket' => env('QINIU_BUCKET'),
    'domain' => env('QINIU_DOMAIN'),
],

第三步:.env 文件中填写配置

// .env
QINIU_ACCESS_KEY=你的七牛 key
QINIU_SECRET_KEY=你的七牛 secret
QINIU_BUCKET=你的七牛 bucket
QINIU_DOMAIN=对应 BUCKET 的域名

第四步:创建控制器

<?php
// App\Controller\Test\QiNiuUploadController.php

namespace App\Controller\Test;

use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\View\RenderInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Contract\ConfigInterface;
use League\Flysystem\Config;

#[Controller]
class QiNiuUploadController
{
}

项目根目录准备一些图片,后续上传图片需要使用。

到此,准备工作已经完成,接下来使用两种不同的方法来实现文件上传。

上传图片到七牛

方法一:通过实例方式上传

需要注意引入的文件,很容易就引入错误的文件了。

上传图片案例

#[PostMapping('/qiniu/store')]
public function store()
{
    // 实例化容器对象
    $container         = ApplicationContext::getContainer();
    // 实例 Config 配置对象,并获取 file.php 配置文件内容
    $options           = $container->get(ConfigInterface::class)->get('file');
    // 获取文件工厂实例
    $filesystemFactory = $container->get(FilesystemFactory::class);
    // 获取七牛实例对象
    $adapter           = $filesystemFactory->getAdapter($options, 'qiniu');

    $path = 'a.jpg';
    if ($adapter->fileExists($path)) {
        // 文件存在,则返回 URL
        return  $adapter->getUrl($path);
    }

    // 上传图片
    $adapter->writeStream($path,fopen($path, 'r'), new Config());

    return $adapter->getUrl($path);
}

上传文件案例

#[PostMapping('/qiniu/store')]
public function store()
{
    // 实例化容器对象
    $container         = ApplicationContext::getContainer();
    // 实例 Config 配置对象,并获取 file.php 配置文件内容
    $options           = $container->get(ConfigInterface::class)->get('file');
    // 获取文件工厂实例
    $filesystemFactory = $container->get(FilesystemFactory::class);
    // 获取七牛实例对象
    $adapter           = $filesystemFactory->getAdapter($options, 'qiniu');

    $path = 'hyperf.txt';
    $content = 'hyperf 3 上传文件';
    if ($adapter->fileExists($path)) {
        // 文件存在,则返回 URL
        return  $adapter->getUrl($path);
    }

    // 上传文件
    $adapter->write($path, $content, new Config());
    
    return $adapter->getUrl($path);
}

上传文件与上传图片本质是一样的,都是文件。当上传文件时,只是将方法改变了,其余的没有改动。

方法二:使用依赖注入

时间:2023-3-12

很遗憾,参考官方文档提供的依赖注入方式,未能实现上传。那么接着对方法一的案例进行改造。

1、通过 Hyperf\Filesystem\FilesystemFactory; 实现

第一步:控制器

<?php

namespace App\Controller\Test;

use Hyperf\Contract\ContainerInterface;
use Hyperf\Filesystem\Adapter\QiniuAdapterFactory;
use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\View\RenderInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Contract\ConfigInterface;
use League\Flysystem\Config;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemAdapter;

#[Controller]
class QiNiuUploadController
{
    protected \League\Flysystem\FilesystemAdapter $adapter;
    
    public function __construct(protected ContainerInterface $container, $adapterName = 'qiniu')
    {
        $this->adapter    = $this->getAdapter($adapterName);
    }

    public function getAdapter($adapterName)
    {
        $options           = $this->container->get(ConfigInterface::class)->get('file');
        $filesystemFactory = $this->container->get(FilesystemFactory::class);

        return $filesystemFactory->getAdapter($options, $adapterName);
    }

    #[GetMapping('/qiniu/create')]
    public function create(RenderInterface $render)
    {
        return $render->render('qiniu.create');
    }

    #[PostMapping('/qiniu/store')]
    public function store(RequestInterface $request)
    {
        if ($request->hasFile('file')) {
            $file        = $request->file('file');
            $stream      = fopen($file->getRealPath(), 'r+');
            $newFilename = 'images/' . date('YmdHis') . uniqid() . '.' . $file->getExtension();
            $this->adapter->writeStream($newFilename, $stream, new Config());;
            fclose($stream);

            return $this->adapter->getUrl($newFilename);
        }
    }
}

第二步:视图文件

<!-- storage/view/qiniu/create.blade.php -->
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Hyperf 3 上传图片</title>
</head>
<body>
    <form action="/qiniu/store" method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="上传图片">
    </form>
</body>
</html>

2、使用 \League\Flysystem\Filesystem $filesystem 对象实现

这一步只修改修改控制器对的方法即可,如下:

<?php

namespace App\Controller\Test;

use Hyperf\Contract\ContainerInterface;
use Hyperf\Filesystem\Adapter\QiniuAdapterFactory;
use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\View\RenderInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Contract\ConfigInterface;
use League\Flysystem\Config;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemAdapter;

#[Controller]
class QiNiuUploadController
{
    protected \League\Flysystem\FilesystemAdapter $adapter;

    protected $filesystem;

    public function __construct(protected ContainerInterface $container, $adapterName = 'qiniu')
    {
        $this->adapter    = $this->getAdapter($adapterName);
        // 改动此处
        // 实例化 Filesystem 对象
        $this->filesystem = new Filesystem($this->adapter);
    }

    public function getAdapter($adapterName)
    {
        $options           = $this->container->get(ConfigInterface::class)->get('file');
        $filesystemFactory = $this->container->get(FilesystemFactory::class);

        return $filesystemFactory->getAdapter($options, $adapterName);
    }

    #[GetMapping('/qiniu/create')]
    public function create(RenderInterface $render)
    {
        return $render->render('qiniu.create');
    }

    #[PostMapping('/qiniu/store')]
    public function store(RequestInterface $request)
    {
        if ($request->hasFile('file')) {
            $file        = $request->file('file');
            $stream      = fopen($file->getRealPath(), 'r+');
            $newFilename = 'images/' . date('YmdHis') . uniqid() . '.' . $file->getExtension();
            // 改动此处
            // 使用 League\Flysystem\Filesystem 上传
            $this->filesystem->writeStream($newFilename, $stream);
            fclose($stream);

            return $this->adapter->getUrl($newFilename);
        }
    }
}

自己可以封装一个上传类出来,这里暂时就不分装了,不是本篇文章的范畴。

请登录后再评论