Laravel-medialibrary: Updating image/file for existing media records

Created on 13 Apr 2017  路  7Comments  路  Source: spatie/laravel-medialibrary

There is no simple way to update the image of an existing media record.
The package appears to be written with the intent to never update the image of an existing media record. I'm not sure why this is the case, maybe there is a good reason for this I am missing.

Use Case:

An app with blog posts that have zero or more attached media records. The blog post editing ui has a list view of each media record attached displaying the file/image, title, and description of each media record (title and description are stored in media.custom_properties).

A user is editing a post with multiple images attached with titles and descriptions. There is a media record that they wish to update the image of but want to keep the title and description they have already written for it.

Building this list view using a front-end that makes changes via an async api becomes unusually difficult. You have a collection of media records on the front end using media.id as the unique identifier of each list item. It is easy to update all the data of an existing media record except the image/file. Abstracting the updating of an existing media item by creating a new one to replace it complicates syncing the data changes with the front end as the id of the media item has changed.

I'm very surprised no one has mentioned this case before.
After digging into the code I realize adding this would take some work. I would be happy to make a PR. Would the Spatie group be open to discussing how best implement this?

Most helpful comment

Is there a reason why? I thought I provided a reasonable case.

All 7 comments

This is a reduced case of my current solution for updating the file of an existing media item.

I have not yet tackled triggering regeneration of the media records conversions.

namespace App\Models;

use Spatie\MediaLibrary\FileManipulator;
use Spatie\MediaLibrary\Media as BaseMedia;
use Spatie\MediaLibrary\Helpers\File;

class Media extends BaseMedia {

    public function updateFile($newFile) {

        $fileName        = $newFile->getClientOriginalName();
        $fileName        = $this->sanitizeFileName($fileName);
        $currentFileName = $this->file_name;
        $path            = $newFile->path();
        $fileSystem      = app(\Spatie\MediaLibrary\Filesystem\Filesystem::class);

        $this->name      = pathinfo($fileName, PATHINFO_FILENAME);
        $this->file_name = $fileName;
        $this->mime_type = File::getMimetype($path);
        $this->size      = filesize($path);

        $fileSystem->removeFiles($this);

        // overwrite current file keep old name
        $fileSystem->copyToMediaLibrary($path, $this, false, $currentFileName);

        // when this model is saved, the file will be renamed appropriately to $fileName via $media->file_name
    }

    public function setCustomProperties(array $properties) {
        foreach ($properties as $key => $val) {
            $this->setCustomProperty($key, $val);
        }
    }

    protected function sanitizeFileName(string $fileName): string {
        return str_replace(['#', '/', '\\'], '-', $fileName);
    }

    public function regenerate(){

        /** @var FileManipulator $fileManipulator */
        $fileManipulator = app(FileManipulator::class);
        $fileManipulator->createDerivedFiles($this);
    }
}

// usage in route
Route::post('media/{media}/update-file', function (Request $request, Media $media) {

    $newFile = $request->file('new_file');
    $media->updateFile($newFile);
});

Thank you for this code, but we're probably not going to add this feature to the package. If you want to replace a media item, just delete the old one and create a new one (with the newer files) and set its properties to the same values as the old media item.

Is there a reason why? I thought I provided a reasonable case.

I also think that ->replace($name = 'logo') would be useful

Hello Freek, I think it could be very useful to be able update a record since you want to include a media manager in your cms where you can update some infos, upload new file, etc.
(like in Wordpress to use a famous example ;)

@unstoppablecarl @canvural Please is there a way I can upload new image[s] to an existing model? In my situation, I created a Property form that accepts multiple property images which work well, but the problem is when trying to update that Property Model to accepts more image whenever the user clicks on update form, I get the same error as above.
Here is it for update function.
foreach ($request->file('property_photos', []) as $key => $file) { $property->addMedia($file) ->preservingOriginal() ->toMediaCollection('property_image'); }
For this update, I want to add more images to the existing image in the Property Model without having to delete previous uploaded image

There is not a reasonable way to do it with this package. You have to delete and create.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ideadx picture ideadx  路  4Comments

stayallive picture stayallive  路  4Comments

netanelwebninja picture netanelwebninja  路  3Comments

brendt picture brendt  路  4Comments

snapey picture snapey  路  3Comments