21、Hyperf 3 快速使用 - Hyperf 3 上传文件 or 图片到七牛云
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);
}
}
}
自己可以封装一个上传类出来,这里暂时就不分装了,不是本篇文章的范畴。
请登录后再评论