Laravel Spatie的媒体库:如何下载多个文件并将它们压缩在目录中

问题描述

我正在使用Spatie's Media Library上传文件

然后,我允许用户使用以下方法下载一组特定的文件

return MediaStream::create('prefix-'.$model->name.'.zip')->addMedia($mediaFiles);

在macOS中,我下载了该zip文件,当我双击它时,它会自动解压缩文件并将其保存在一个文件夹中,该文件夹的名称与.zip文件名中指定的名称相同(例如prefix-model.zip )。到现在为止还挺好。但是,Windows 10用户报告说,使用WinZip解压缩的文件并没有在文件夹内解压缩,只有文件解压缩了。

为什么会这样?还是有一种变通办法或其他方法来确保.zip文件文件夹内解压缩,而不在没有文件夹的情况下不直接解压缩文件

这是所有方法的类别:

<?PHP

namespace Spatie\MediaLibrary\Support;

use Illuminate\Contracts\Support\Responsable;
use Illuminate\Support\Collection;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Symfony\Component\HttpFoundation\StreamedResponse;
use ZipStream\Option\Archive as ArchiveOptions;
use ZipStream\ZipStream;

class MediaStream implements Responsable
{
    protected string $zipName;

    protected Collection $mediaItems;

    protected ArchiveOptions $zipOptions;

    public static function create(string $zipName)
    {
        return new static($zipName);
    }

    public function __construct(string $zipName)
    {
        $this->zipName = $zipName;

        $this->mediaItems = collect();

        $this->zipOptions = new ArchiveOptions();
    }

    public function useZipOptions(callable $zipOptionsCallable): self
    {
        $zipOptionsCallable($this->zipOptions);

        return $this;
    }

    public function addMedia(...$mediaItems): self
    {
        collect($mediaItems)
            ->flatMap(function ($item) {
                if ($item instanceof Media) {
                    return [$item];
                }

                if ($item instanceof Collection) {
                    return $item->reduce(function (array $carry,Media $media) {
                        $carry[] = $media;

                        return $carry;
                    },[]);
                }

                return $item;
            })
            ->each(fn (Media $media) => $this->mediaItems->push($media));

        return $this;
    }

    public function getMediaItems(): Collection
    {
        return $this->mediaItems;
    }

    public function toResponse($request): StreamedResponse
    {
        $headers = [
            'Content-disposition' => "attachment; filename=\"{$this->zipName}\"",'Content-Type' => 'application/octet-stream',];

        return new StreamedResponse(fn () => $this->getZipStream(),200,$headers);
    }

    public function getZipStream(): ZipStream
    {
        $zip = new ZipStream($this->zipName,$this->zipOptions);

        $this->getZipStreamContents()->each(function (array $mediaInZip) use ($zip) {
            $stream = $mediaInZip['media']->stream();

            $zip->addFileFromStream($mediaInZip['fileNameInZip'],$stream);

            if (is_resource($stream)) {
                fclose($stream);
            }
        });

        $zip->finish();

        return $zip;
    }

    protected function getZipStreamContents(): Collection
    {
        return $this->mediaItems->map(fn (Media $media,$mediaItemIndex) => [
            'fileNameInZip' => $this->getZipFileNamePrefix($this->mediaItems,$mediaItemIndex).$this->getFileNameWithSuffix($this->mediaItems,$mediaItemIndex),'media' => $media,]);
    }

    protected function getFileNameWithSuffix(Collection $mediaItems,int $currentIndex): string
    {
        $fileNameCount = 0;

        $fileName = $mediaItems[$currentIndex]->file_name;

        foreach ($mediaItems as $index => $media) {
            if ($index >= $currentIndex) {
                break;
            }

            if ($this->getZipFileNamePrefix($mediaItems,$index).$media->file_name === $this->getZipFileNamePrefix($mediaItems,$currentIndex).$fileName) {
                $fileNameCount++;
            }
        }

        if ($fileNameCount === 0) {
            return $fileName;
        }

        $extension = pathinfo($fileName,PATHINFO_EXTENSION);
        $fileNameWithoutExtension = pathinfo($fileName,PATHINFO_FILENAME);

        return "{$fileNameWithoutExtension} ({$fileNameCount}).{$extension}";
    }

    protected function getZipFileNamePrefix(Collection $mediaItems,int $currentIndex): string
    {
        return $mediaItems[$currentIndex]->hasCustomProperty('zip_filename_prefix') ? $mediaItems[$currentIndex]->getCustomProperty('zip_filename_prefix') : '';
    }
}

There are several options here,但是似乎没有任何方法可以强制将文件保存在文件夹中……是吗?

这些方法中的任何一种都可以帮助我强制在文件夹内压缩吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)