我正在使用Spatie 的媒体库上传文件。
然后,我允许用户使用以下方法下载一组特定的文件:
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') : '';
}
}
这里有几个选项,但似乎没有任何方法可以强制将文件保存在文件夹中......是吗?
这些方法中的任何一种都可以帮助我在文件夹中强制压缩吗?