【问题标题】:Handling pre-existing images when editing a model using Livewire & Filepond使用 Livewire 和 Filepond 编辑模型时处理预先存在的图像
【发布时间】:2021-05-24 08:17:40
【问题描述】:

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

但是,当我需要编辑帖子及其预先存在的图像时,我在使用 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 中临时文件数组中图像的顺序不同。临时文件数组是按照图像上传的顺序创建的。文件池顺序是添加图像的顺序。我已经完全放弃了使用 filepond 和 livewire 来重新排序图像。

标签: laravel laravel-livewire filepond


【解决方案1】:

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

为了我们处理图像的重新排序,我们需要一个来自服务器的唯一标识符,并且使用 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
}

这是为什么呢?我们第一次通过文件池的files array 或addFile method 添加图像时,我们使用livewire 的@this.upload('images', file, load, error, progress) 处理图像。这里的加载回调是返回 serverId 或我们需要的唯一标识符,以便 Filepond 可以与后端进行通信。来自 filepond 的加载回调在 server process object 中可用,但在 onreorderfiles 事件中不可用。

这不太正确,但我们确实知道在哪里可以找到 serverId。查看livewire的livewire\livewire\js\UploadManager.js的源代码,我们会找到上传方法,它确实返回了tmpFilename:

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

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

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

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

    // omitted code
}

总结

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

更改以下代码块:

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

对此,请记住,livewire 上传方法无论如何都会返回唯一的文件名,但我们需要将它传递给 filepond 并且 load 方法接受一个响应作为参数:

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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-05
    • 2014-12-16
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2020-10-03
    • 2019-11-19
    • 2022-06-10
    相关资源
    最近更新 更多