使用 Livewire 和 Filepond 编辑模型时处理预先存在的图像

Handling pre-existing images when editing a model using Livewire & Filepond

我有一个 Filepond 组件,非常适合将图像上传到 post。

但是,当我需要编辑 post 及其预先存在的图像时,我正在努力使用 Filepond。

我想用 Post 模型的预先存在的图像加载 Filepond。目标是允许用户在编辑 Post 模型时上传、删除和重新排序图像,然后更新数据库和文件系统。

这是我目前拥有的:

<div
        x-data=""
        x-init="
            // Plugins
            FilePond.registerPlugin(FilePondPluginImagePreview);
            FilePond.registerPlugin(FilePondPluginImageExifOrientation);
            FilePond.registerPlugin(FilePondPluginFileValidateType);
            FilePond.registerPlugin(FilePondPluginFileValidateSize);
            FilePond.registerPlugin(FilePondPluginImageResize);

            // Set options
            FilePond.setOptions({
                allowMultiple: true,
                allowReorder: true,
                itemInsertLocation: 'after',
                server: {
                    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
                        @this.upload('images', file, load, error, progress)
                    },
                    revert: (filename, load) => {
                        @this.removeUpload('images', filename, load)
                    },
                },
                // This allows me to reorder the images, essential resetting the $image variable in livewire component when ever th euser reorders the images in filepond
                onreorderfiles(files, origin, target){
                    @this.set('images', null);
                    files.forEach(function(file) {
                        @this.upload('images', file.file);
                    });
                },

            });

            // Create Filepond
            const pond = FilePond.create($refs.input, {
                acceptedFileTypes: ['image/png', 'image/jpeg'],
                
                @if(optional($post)->images) // If we are editing a post and if that post has images
                files: [
                    @foreach($post->images as $image)// Loop through each image for the post
                        {
                            // the server file reference
                            source: '{{ Storage::disk('post_images')->url($post->id . '/' . $image->filename.$image->extension) }}', 
                        },
                    @endforeach
                ],
                @endif
            });

            pond.on('addfile', (error, file) => {
                if (error) {
                    console.log('Oh no');
                    return;
                }
            });
        "
    >
        <div wire:ignore wire:key="images">
                <input
                    id="image-upload"
                    type="file"
                    x-ref="input"
                    multiple
                >

                @error('images.*')
                <p wire:key="error_images" class="mt-2 text-sm text-red-600" id="email-error">{{ $message }}</p>
                @enderror
        </div>
    </div>

然而,这会导致每次用户查看编辑页面时重新上传所有图像。

网上有很多关于如何使用 filepond 和 livewire 上传图片的资料,但关于如何编辑的资料并不多。

除了每次用户查看编辑页面时重新上传之外,还有更好的管理图片的方法吗?

如有任何帮助,我们将不胜感激。

我能够处理模型上预先存在的图像,特别是我能够重新排序图像

为了我们处理图像的重新排序,我们需要一个来自服务器的唯一标识符,而 livewire 的 upload method 神奇地为我们处理了它。

@this.upload('images', file, load, error, progress)

这很好,可以同时处理或恢复上传,但当我们尝试侦听 filepond 的 onreorderfile 事件时中断。 Filepond 知道如何处理 DOM 级别的重新排序,但缺少重要信息,即来自服务器的唯一标识符

onreorderfiles(files, origin, target) {
    console.log(file.serverId); // this will be null
}

这是为什么?我们第一次通过 filepond 的 files array or addFile method we processed the images using livewire's @this.upload('images', file, load, error, progress). The load callback here is what returns the serverId or the unique identifier we need so that Filepond can communicate it with the backend. The load callback from filepond is available on the server process object 添加图像,而不是在 onreorderfiles 事件中。

这不太正确,但我们确实知道在哪里可以找到 serverId。深入了解 livewire livewire\livewire\js\UploadManager.js 的源代码,我们将找到上传方法,它执行 return tmpFilename:

this.component.on('upload:finished', (name, tmpFilenames) => this.markUploadFinished(name, tmpFilenames))

问题很明显,因为 onreorderfiles 事件我们没有指定对 filepond 的 load() 方法的任何回调,并且当脚本到达服务器进程对象时 load 未定义:

onreorderfiles(files, origin, target){
    // omitted code

    @this.upload('images', file.file);

    // omitted code
}

总结

解决方案是无论如何显式return一个成功回调。

更改以下代码块:

server: {
    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
        @this.upload('images', file, load, error, progress)
},

对此,请记住 livewire 上传方法 return 的唯一文件名无论如何,但我们需要将其传递给 filepond 并且加载方法接受响应作​​为参数:

server: {
    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
        @this.upload('images', file,
            // this is the secret method people have been looking for
            (uploadedFilename) => {
                load(uploadedFilename);
            }, error, progress)
},

好吧,这不是秘密 本身 因为它记录在 Livewire file uploads.