Laravel Flysystem 与 Zip Archive Adapter 的集成

zer*_*nes 2 php filesystems zip laravel

该文档说明了如何集成 dropbox flysystem 适配器,但没有向您展示如何与 ZipArchive 适配器或类似的集成。

https://laravel.com/docs/5.4/filesystem#custom-filesystems

https://github.com/thephpleague/flysystem-ziparchive

我尝试阅读 FilesystemManager.php 上的方法,该类包含文档示例中使用的扩展方法。我找到了一个叫做 adapt 的方法,它看起来可能是票。

我尝试从 Storage 门面调用此方法,如下所示:

return $storage_with_zip = Storage::adapt(new \League\Flysystem\ZipArchive\ZipArchiveAdapter($file->getRealPath()));

但我收到此错误:

BadMethodCallException Call to undefined method League\Flysystem\Filesystem::adapt

有没有人成功地将 Laravel 文件系统与 ZipArchiveAdapter 集成?我知道我只能使用 PHP 原生 ZipArchive,但我希望文件系统中的所有内容都使用 Laravel 包装器。

谢谢!

***更新

我的最终目标是能够将上传的 zip 解压缩到 storage/ 目录或 s3。

示例 1) $file = Storage::disk('local')->extractTo('unzipped/', $file);

而不是这个:

$zip = new ZipArchive(); 
$zip->open($file->getRealPath()); 
$zip->extractTo(storage_path('app') . 'unzipped');
Run Code Online (Sandbox Code Playgroud)

例 2) $file = Storage::disk('s3')->extractTo('unzipped/', $file);

PiK*_*Kos 6

对于你想做的事情,最好为 League\Flyststem 创建一个插件。我不确定是否有一种“干净”的方式将插件添加到 Laravel-Flyststem,它是 League\Flyststem 和 Laravel 之间的桥梁。一种解决方法是为 local/s3 注册一个自定义驱动程序,它将通过注入 zip 插件扩展嵌入式驱动程序。

有几个步骤可以实现它:

1) 在 App/Filesystem/Plugins 中创建 ZipExtractTo 插件

ZipExtractTo

namespace App\Filesystem\Plugins;

use League\Flysystem\Plugin\AbstractPlugin;
use ZipArchive;

class ZipExtractTo extends AbstractPlugin
{
    /**
     * @inheritdoc
     */
    public function getMethod()
    {
        return 'extractTo';
    }

    /**
     * Extract zip file into destination directory.
     *
     * @param string $path Destination directory
     * @param string $zipFilePath The path to the zip file.
     *
     * @return bool True on success, false on failure.
     */
    public function handle($path, $zipFilePath)
    {
        $path = $this->cleanPath($path);

        $zipArchive = new ZipArchive();
        if ($zipArchive->open($zipFilePath) !== true) 
        {
            return false;
        }

        for ($i = 0; $i < $zipArchive->numFiles; ++$i) 
        {
            $zipEntryName = $zipArchive->getNameIndex($i);
            $destination = $path . DIRECTORY_SEPARATOR . $this->cleanPath($zipEntryName);
            if ($this->isDirectory($zipEntryName)) 
            {
                $this->filesystem->createDir($destination);
                continue;
            }
            $this->filesystem->putStream($destination, $zipArchive->getStream($zipEntryName));
        }

        return true;
    }

    private function isDirectory($zipEntryName) 
    {
        return substr($zipEntryName, -1) ===  '/';
    }

    private function cleanPath($path)
    {
        return str_replace('/', DIRECTORY_SEPARATOR, $path);
    }

}
Run Code Online (Sandbox Code Playgroud)

2) 为 local/s3 创建提供者:

扩展本地服务提供者

namespace App\Providers;

use Storage;
use Illuminate\Support\ServiceProvider;
use App\Filesystem\Plugins\ZipExtractTo;

class ExtendedLocalServiceProvider extends ServiceProvider 
{
    public function boot()
    {
        Storage::extend('local', function($app, $config) {
            return Storage::createLocalDriver($config)->addPlugin(new ZipExtractTo());
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

扩展S3服务提供者

namespace App\Providers;

use Storage;
use Illuminate\Support\ServiceProvider;
use App\Filesystem\Plugins\ZipExtractTo;

class ExtendedS3ServiceProvider extends ServiceProvider 
{
    public function boot()
    {
        Storage::extend('s3', function($app, $config) {
            return Storage::createS3Driver($config)->addPlugin(new ZipExtractTo());
        });        
    }
}
Run Code Online (Sandbox Code Playgroud)

3) 在 app.php 中注册提供者

'providers' => [
 ...
 App\Providers\ExtendedLocalServiceProvider::class,
 App\Providers\ExtendedS3ServiceProvider::class,
],
Run Code Online (Sandbox Code Playgroud)

4)现在你可以做这样的事情:

Storage::disk('local')->extractTo('unzipped/', $zipPath);
Storage::disk('s3')->extractTo('unzipped/', $zipPath);
Run Code Online (Sandbox Code Playgroud)