spatie / laravel-medialibrary

Associate files with Eloquent models
https://spatie.be/docs/laravel-medialibrary
MIT License
5.73k stars 1.07k forks source link

Upgraded to v10 and it's completely broken for me... weird UUIDs and empty files #2891

Closed ryanmortier closed 1 year ago

ryanmortier commented 2 years ago

I recently upgraded from PHP 7.4 to PHP 8.1, upgraded Laravel from v8 to v9 (via Laravel Shift), and upgraded media library from v9 to v10.

Everything else is working great except this library.

I'm also using Media Library Pro components. When uploading a file, the files are empty and both GD and Imagick complain due to the file being 0 bytes.

GD gives me the following:

Unsupported image type application/x-empty. GD driver is only able to decode JPG, PNG, GIF, BMP or WebP files.

Imagick gives me the following:

Unable to read image from path (/tmp/Glide8fN9rc).

This is what my storage directory looks like after a clean install:

image

This is what it looks like after simply dragging a file into the pro collection component (without saving the form):

image

And if I click save, this is what it looks like:

image

Livewire Component:

<?php

namespace App\Http\Livewire\Orders;

use App\Models\Order;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;
use Spatie\MediaLibraryPro\Http\Livewire\Concerns\WithMedia;

class PhotoComponent extends Component
{
    use AuthorizesRequests, WithMedia;

    public Order $order;

    public $mediaComponentNames = ['photos'];

    public $photos;

    public function save()
    {
        $this->authorize('update', $this->order);

        $this->order->syncFromMediaLibraryRequest($this->photos)->toMediaCollection('photos');

        $this->order->refresh();

        $this->dispatchBrowserEvent('photos-saved');
    }

    public function render()
    {
        return view('livewire.orders.photo-component');
    }
}

This is my composer.json file:

    "require": {
        "php": "^8.0.2",
        "doctrine/dbal": "^3.3",
        "guzzlehttp/guzzle": "^7.4",
        "laravel/framework": "^9.7",
        "laravel/sanctum": "^2.15",
        "laravel/tinker": "^2.7",
        "laravel/ui": "^3.4",
        "livewire/livewire": "^2.10",
        "nesbot/carbon": "^2.57",
        "spatie/browsershot": "^3.52",
        "spatie/laravel-medialibrary": "^10.3",
        "spatie/laravel-medialibrary-pro": "^2.3",
        "spatie/laravel-permission": "^5.5",
        "spatie/laravel-ray": "^1.29"
    },

Model:

<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class Order extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia;

    protected $guarded = [];

    protected $with = ['meta'];

    public $timestamps = false;

    public function registerMediaConversions(Media $media = null): void
    {
        $this->addMediaConversion('preview')
            ->fit(Manipulations::FIT_CROP, 300, 300)
            ->nonQueued();

        $this->addMediaConversion('normal')->fit(Manipulations::FIT_CONTAIN, 1152, 864);
    }

    public function meta()
    {
        return $this->hasOne(OrderMeta::class)->withDefault();
    }
}

View:

<x-modal wire:ignore.self id="modal-photos" size="modal-lg">
    <x-slot name="header">
        <h5 class="modal-title">Manage Photos</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
    </x-slot>
    <x-slot name="body">
        <form wire:submit.prevent="save" id="form-photos" autocomplete="off">
            <x-media-library-collection name="photos" :model="$order" collection="photos" rules="mimes:jpeg,png|max:3072" />
        </form>
    </x-slot>
    <x-slot name="footer">
        <button type="submit" class="btn btn-primary" form="form-photos">
            <span wire:loading.delay wire:target="save" class="spinner-border spinner-border-sm"></span>
            Save
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
    </x-slot>
</x-modal>

Database:

image

I'm not doing anything out of the ordinary here, I have no idea why it broke? I've cleared caches, reinstalled, cloned from source, etc.

Another thing is that I have a conversion (normal) that should be queuing (see registerMediaConversions on model) into the jobs table on the database but no job is ever created.

ryanmortier commented 2 years ago

I've managed to make some very minor changes and get things working temporarily. The issue appears to be related to the pro components or the syncFromMediaLibraryRequest method.

In my Livewire component, I changed the following:

From

$this->order->syncFromMediaLibraryRequest($this->photos)->toMediaCollection('photos');

To

foreach ($this->photos as $photo) {
    $this->order->addMedia($photo)->toMediaCollection('photos');
}

and on my view I stopped using the pro components:

From

<form wire:submit.prevent="save" id="form-photos" autocomplete="off">
    <x-media-library-collection name="photos" :model="$order" collection="photos" rules="mimes:jpeg,png|max:3072" />
</form>

To

<form wire:submit.prevent="save" id="form-photos" autocomplete="off">
    <input type="file" wire:model="photos" multiple>
</form>

These two simple changes makes everything work. My queue is processing conversion jobs, the files are all named normally without uuids, etc.

Storage:

image

Database:

image

timothyasp commented 2 years ago

I'm also getting this exact error.

Very similar scenario, upgrading from 7.4 to 8.0, and L7 to L9. and ML 9 to 10

But no livewire.

The solution you came to @ryanmortier seems to be just not using the pro components?

timothyasp commented 2 years ago

Specifically, this happens for me when the vapor param is set on the <media-library-collection> component. When I remove the vapor param, things work as expected.

The temporary image is uploaded to S3, and verified that it's on S3 as expected.

But when the medialibrary attempts manipulations, it writes the image to /tmp and the image is empty, causing the above errors.

no decode delegate for this image format' @ error/constitute.c/ReadImage/572` https://d.pr/i/FiGzdR

timothyasp commented 2 years ago

I think https://github.com/spatie/laravel-medialibrary/commit/06a0e949c9d9c64be208993be0f79a54cd8680cb commit might be the culprit.

ryanmortier commented 2 years ago

The solution you came to @ryanmortier seems to be just not using the pro components?

Yeah pretty much. I'm hoping to one day add them back in but there is like zero support for these components and I don't have time to dig into it.

morris14 commented 2 years ago

Thanks for the incredible package everyone at Spatie!

I'm getting the exact same error. My assets SHOULD be saved in a "bucket_assets" directory. When using the pro react component to select a file from my computer, my storage folder looks like so:

image

Once I click upload, it then looks like this:

image

Notice at the root of my storage directory I'm left with a random directory with a uuid as a name, with an image inside it. Yet the rest is moved correctly to the bucket_assets directory.

This is frustrating as this random folder never seems to get garbage collected, so it'll just clog up the storage folder. I've also noticed that the media-library/temp directory is never used.

timothyasp commented 2 years ago

The solution you came to @ryanmortier seems to be just not using the pro components?

Yeah pretty much. I'm hoping to one day add them back in but there is like zero support for these components and I don't have time to dig into it.

Yea.. It's tough because when you pay $300 for a license annually, you expect to be able to use it.

jackrstevens commented 2 years ago

The solution you came to @ryanmortier seems to be just not using the pro components?

Yeah pretty much. I'm hoping to one day add them back in but there is like zero support for these components and I don't have time to dig into it.

Yea.. It's tough because when you pay $300 for a license annually, you expect to be able to use it.

I'm having this issue as well since doing updates. Pretty massive issue since, as you say, this is licensed software.

Has anybody had any update on this?

freekmurze commented 2 years ago

I'll be taking a look at this next week (sorry for the wait). Could anybody confirm that these issues are occurring when you use our demo app? A minimal app that showcases the problem would help a lot.

ryanmortier commented 2 years ago

I setup the demo app and was unsuccessful at replicating the issue. The demo app seems to work fine which is weird because my implementation is very basic/default so I can't possibly see where the issue might be. Unfortunately I can't share my application due to it being private and not owned by myself but I'm hoping someone else can share theirs?

timothyasp commented 2 years ago

I had this issue on php81 on vapor, so I’ll see if I can recreate it there.

On Fri, Jun 3, 2022 at 7:55 AM Ryan Mortier @.***> wrote:

I setup the demo app and was unsuccessful at replicating the issue. The demo app seems to work fine which is weird because my implementation is very basic/default so I can't possibly see where the issue might be. Unfortunately I can't share my application due to it being private and not owned by myself but I'm hoping someone else can share theirs?

— Reply to this email directly, view it on GitHub https://github.com/spatie/laravel-medialibrary/issues/2891#issuecomment-1146046529, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFMY42RT3E2P2W333HN36LVNIMGLANCNFSM5TZWRSPA . You are receiving this because you commented.Message ID: @.***>

-- -Tim

phuclh commented 2 years ago

I am still getting this error without using the pro package.

CleanShot 2022-06-17 at 16 22 37@2x

astonge commented 2 years ago

Was having the same issue today with medialibrary-notpro.. I added the following to my .env:

VAPOR_ARTIFACT_NAME=true

My AWS/S3 related section (using minio locally):

VAPOR_ARTIFACT_NAME=true
AWS_ACCESS_KEY_ID=adminusername
AWS_SECRET_ACCESS_KEY=adminpassword
AWS_DEFAULT_REGION=us-west-1
AWS_BUCKET=website-assets
AWS_ENDPOINT=http://10.0.0.5:9000
AWS_USE_PATH_STYLE_ENDPOINT=false

Hope that helps anyone else having the same issues.

morris14 commented 2 years ago

Hey @freekmurze, appreciate you are busy 👌! Any movement on this at all?

freekmurze commented 2 years ago

It would help if somebody could PR a failing test for me to look at.

gingebaker commented 2 years ago

I'll be taking a look at this next week (sorry for the wait). Could anybody confirm that these issues are occurring when you use our demo app? A minimal app that showcases the problem would help a lot.

In my case I could recreate the issue with the demo app and sail with wsl2 on windows. I created an issue in the laravel-medialibrary-pro: https://github.com/spatie/laravel-medialibrary-pro/issues/460#issuecomment-1195734788

ryanmortier commented 2 years ago

Maybe WSL2 is the common denominator? I was also using WSL2.

topegret commented 2 years ago

test with demo repo on a local server

https://github.com/spatie/laravel-medialibrary-pro-app/issues/54

ryanmortier commented 2 years ago

I just bought a MacBook. If I have time this weekend, I'll try to see if I can isolate the issue to WSL2 in my case.

gingebaker commented 2 years ago

I had the same problem with these hashed folder names not getting deleted when using the medialibrary-pro upload components. I found a workaround wich includes overwriting the "TemporaryUploadPathGenerator". see: https://github.com/spatie/laravel-medialibrary-pro/issues/460#issuecomment-1205325012

I had this issue on windows and also on debian linux server with Apache/PHP Standard Installation.

ramonfeleus commented 2 years ago

I have the same error as well in 2 projects: Intervention\Image\Exception\NotReadableException: Unsupported image type application/x-empty. GD driver is only able to decode JPG, PNG, GIF, BMP or WebP files. in file _PROJECTROOT_/vendor/intervention/image/src/Intervention/Image/Gd/Decoder.php on line 75. These both are projects which have upgraded to laravel 9 (from 8). One project is the base for our Nova 3 projects modified for laravel 9. The other is the same, but for Nova 4. It happens with both when I upload an image. For images I'm using a S3 disk configured to use the SIRV image hosting platform.

.env file S3 config: AWS_ACCESS_KEY_ID="mymail@example.org" AWS_SECRET_ACCESS_KEY="XXXXXXXXXXXXXXX" AWS_DEFAULT_REGION=europe-west-1 AWS_BUCKET="mybucket" AWS_URL="https://images.ourdomain.nl" AWS_ENDPOINT="https://s3.sirv.com" SIRV_ROOTDIR="projectdir" config/filesystems.php disks section: ` .... 'disks' => [

    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
        'throw' => false,
    ],

    'public' => [
        'driver' => 'local',
        'root' => storage_path('app/public'),
        'url' => env('APP_URL').'/storage',
        'visibility' => 'public',
        'throw' => false,
    ],

    's3' => [
        'driver' => 's3',
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'region' => env('AWS_DEFAULT_REGION'),
        'bucket' => env('AWS_BUCKET'),
        'url' => env('AWS_URL'),
        'endpoint' => env('AWS_ENDPOINT'),
        'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
        'throw' => false,
    ],

... ]; `

config/media-library.php is standard, but with: 'disk_name' => env('MEDIA_DISK', 's3'),

I'm working on a macbook, so that should rule out WSL2 issues here.

The issue happens with uploaders from https://github.com/ebess/advanced-nova-media-library (in Nova 4 with laravel 9)as well as a custom https://lian-yue.github.io/vue-upload-component implementation (in Nova 3). The uploaders upload a file through POST as a XHR request to a Nova API url (eg. /nova-vendor/mymodule/action/id).

In the case of the Nova 3 vue-upload-component implementation the file is added to an Mediafolder object ($folder) as follows: ... if ($folder) { $file = $folder ->addMediaFromRequest('file') ->toMediaCollection($isImage ? 'photos' : 'files'); } ... Which throws the error.

The Mediafolder object: ` ... use Spatie\Image\Manipulations; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia;

class Mediafolder extends Model implements HasMedia { use HasFactory, InteractsWithMedia;

.... public function registerMediaConversions(\Spatie\MediaLibrary\MediaCollections\Models\Media $media = null): void { $this->addMediaConversion('nova-thumb') ->width(320) ->height(320); }

public function registerMediaCollections(): void
{
    $this->addMediaCollection('files');

// ->acceptsMimeTypes(['image/jpeg', 'image/png']);

    $this->addMediaCollection('photos')
        ->useDisk('s3')
        ->acceptsMimeTypes(['image/jpeg', 'image/png']);
}

There's no error when I remove the conversions function from this object, however still no successful upload to the S3 disk on Sirv. But a record will be saved to themediatable in the database. It looks okay, just no conversions listed in thegenerated_conversionsfield. When theregisterMediaConversions` is added as above then adding the upload to the object will fail. I hope this gets resolved because the uploads are crucial for our CMS functionality. And as such it's delaying the upgrade to Laravel 9 and Nova 4 for us. Maybe the info above helps to reproduce it.

timothyasp commented 2 years ago

Maybe WSL2 is the common denominator? I was also using WSL2.

I was on a Apple Silicon mac using the latest version of homestead.

ramonfeleus commented 1 year ago

Thanks to @notnek in #3013 I found what the upload issue was in my case. Like suggested in #3013 I added 'throw' => true, to my s3 disk config in config/filesystems.php. This changed the error for me to the following: "AWS HTTP error: cURL error 60: SSL: no alternative certificate subject name matches target host name 'xxx.s3.sirv.com'". The s3 connector tried connecting to a sub-subdomain on sirv.com which did not exist and was not covered by their SSL certificate. In the s3 disk config I then changed use_path_style_endpoint to true. This resulted in a correct handling of the upload and the image was succesfully added to our image hosting. The previous value of use_path_style_endpoint was env('AWS_USE_PATH_STYLE_ENDPOINT', false), which I likely took from examples. In the older laravel 8 nova 3 the value was always set to true. I hope it helps for others as well, at least the throw option should help with debugging.

flamreal commented 1 year ago

I found that this shitty paths generates here: Spatie\MediaLibraryPro\Support\TemporaryUploadPathGenerator and it is md5($media->id . $media->uuid . 'original')

But when I try to attach media $model->syncFromMediaLibraryRequest($request->media)->toMediaCollection('default'); it leads to an error file not found

Because this shitty paths are not used, and library try to find file for attach in normal temporary path (configured by temporary_directory_path param)

Can anyone give advice where the code (which handle the library get path of attaching file) is located?

Ps: it looks like the developers don't care about supporting this library.

gingebaker commented 1 year ago

I found that this shitty paths generates here: Spatie\MediaLibraryPro\Support\TemporaryUploadPathGenerator and it is md5($media->id . $media->uuid . 'original')

Hello @flamreal I had also problems with the Spatie\MediaLibraryPro\Support\TemporaryUploadPathGenerator In my case weird files and folders showed up. I found a way to get rid of them by overwriting the TemporaryUploadPathGenerator. See: https://github.com/spatie/laravel-medialibrary-pro/issues/460#issuecomment-1205325012

flamreal commented 1 year ago

@gingebaker Thanks for replying! (I have a licence, but I couldn't see links to the Pro repo untill I linked spatie acc to github acc =\ It could safe a lot of time for me...)

I try to override this temporary path generator like as you and it helps to return normal folder naming, but it doesn't help to solve file not found error while attaching. fopen(/../storage/media-library/temp/5CrFWXsbqKTIpy9bXhTMJK0hZkWjoy4a//4514006572.jpg): Failed to open stream: No such file or directory

Because library still try to find temporary uploaded file in media-library/temp folder when I try to attach media to media collection: $model->syncFromMediaLibraryRequest($request->media)->toMediaCollection('default'); // got fopen error

Any other advice please?..

flamreal commented 1 year ago

@freekmurze

Could anybody confirm that these issues are occurring when you use our demo app?

I installed fresh clear demo app and confirm this issue. Demo app save this hashed "temporary" directories in public disk, and corruptes when try to manipulate images on http://mlibdemo.test/blade/collection page

Pay attantion to fix this wonderfull "must have" library, please

php - 8.0.24 laravel - 9.36.3 medialibrary - 10.5.2 medialibrary-pro - dev-main

gingebaker commented 1 year ago

I also can confirm the issue with the hashed folder names in the demo app running on wsl2 windows AND on an debian linux server. see my comment from 28th of july. https://github.com/spatie/laravel-medialibrary/issues/2891#issuecomment-1197760014 The workaround here: https://github.com/spatie/laravel-medialibrary-pro/issues/460#issuecomment-1205325012 seems to fix the problem with the hashed folder names.

spatie-bot commented 1 year ago

Dear contributor,

because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.

srfullstackgeek commented 1 year ago

Any update one this?