cybex/laravel-lodor

为Laravel提供处理分块上传的简单支持。


README

Latest Version on Packagist Packagist Downloads Github build status GitHub pull-requests GitHub issues GitHub contributors Laravel Version

此包为Laravel 6.x或更高版本提供了一种简单的方法来实现从前端库(如DropzoneJS或ResumableJS)的简单上传和分块上传,并通过使用Laravel事件实现自定义同步或异步后处理。

由于对6.0.0以下版本的支持已结束,因此该包不支持旧版本的Laravel。

安装

您可以通过composer安装此包

composer require cybex/laravel-lodor

安全

请注意,出于安全原因,默认情况下,上传和轮询路由由web和auth中间件保护。这意味着只有在认证的路由上以及带有CSRF令牌调用时,Lodor才能工作。否则,在尝试上传或轮询时,您将收到HTTP 401响应。

请参阅Laravel CSRF保护文档认证以获取更多信息。

自定义路由中间件

建议始终启用web中间件以确保防止CSRF攻击。然而,有时您可能希望允许未登录的用户上传文件,例如在联系表单中。

您可以通过调整配置中的route_middleware数组来自定义应用于由Lodor注册的路由的中间件。

用法

要开始使用简单的HTML文件上传,您实际上需要做的唯一事情是将文件上传表单的动作设置为Lodor上传路由

<form id="upload-form" enctype="multipart/form-data" method="post" action="{{ Lodor::getUploadRoute() }}">
    @csrf
    <label for="file-input">Upload a file with Lodor:</label>
    <input type="file" name="file" id="file-input" multiple />
    <input type="submit">
</form>

默认情况下,Lodor/uploadmedia处注册了一个POST路由,并且所有简单的上传都会直接进入Laravel应用程序存储路径中的lodor/uploads目录。

上面的HTML表单将文件上传到您的存储目录,并默认返回一个包含成功指示符和uuid的JSON

{"success":true,"uuid":"ffb3dfe7-9029-4b9a-abfe-5e7485592561"}

此设置对于使用JavaScript进行异步上传非常有用,尤其是当使用Dropzone.jsResumable.js之类的库时。

上传后重定向到控制器

如果您想在上传完成后自己处理表单,您可以定义一个名为lodor_uploaded的命名路由,如下所示

Route::post('/uploaded')->uses('SomeController@uploaded')->name('lodor_uploaded');

如果此命名路由存在,Lodor将自动将请求重定向到指定的控制器操作,而不是返回JSON响应。控制器方法应声明如下

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class SomeController extends Controller 
{
   function uploaded(Request $request, bool $success, string $uuid, array $metadata, string $errorMessage = null) {
        // Do something here and handle the request returning some response, view or redirect.
    }
}
  • $request包含文件上传表单的所有请求数据。
  • $success如果上传成功则为true,如果未成功则为false
  • $uuid包含上传的唯一ID。
  • $metadata是一个包含上传文件详细信息的数组。
  • $errormessage包含上传失败时的错误消息,如果没有错误则为null。

分块上传

Lodor自动将上传块合并回单个文件。为了避免由于PHP脚本的执行时间超过最大限制而导致的中断,Lodor默认使用工作队列。如果您无法或不想使用工作进程,您应设置LODOR_MERGE_ASYNC=false环境变量或将merge_chunks.run_async配置设置设置为false(有关详细信息,请参阅配置)。

配置

洛多 的创建考虑到大多数情况下无需配置即可直接使用。然而,您可以将配置文件发布到应用程序的配置目录中,以根据您的需求自定义设置。您可以使用以下命令发布配置

php artisan vendor:publish --provider="Cybex\Lodor\LodorServiceProvider" --tag=config

大多数设置也可以通过环境设置进行调整,您可以在 .env 文件中根据需要设置。

可用的选项及其对应的 env 设置和默认值如下

清理

洛多 在上传失败后触发 UploadFailed 事件或在成功完成后触发 UploadFinished 事件时自动运行清理。在上传失败的情况下,所有文件(包括块和合并后的文件)总是会强制删除,无论您的配置设置如何。

在成功完成上传的情况下,行为取决于多个配置设置。默认情况下,洛多 将在清理过程中删除所有现有文件块,但不会删除上传磁盘中的合并文件。

要更改此默认行为,您可以将 lodor.auto_cleanup_chunks 设置为 false 以在上传后保留块,并将 lodor.auto_cleanup 设置为 true 以在完成上传后(如 UploadFinished 事件所示)始终删除完成的上传。

使用自动清理

在没有任何其他事件监听器注册的基本设置中,洛多在非分块上传成功或分块上传成功合并后始终触发 UploadFinished 事件。因此,默认情况下将 auto_cleanup 设置为 false。如果您将其设置为 true,则上传完成后上传将立即消失。

如果您想使用 auto_cleanup,请确保您注册了 FileUploaded 事件的监听器,通常通过将其添加到您的 EventServiceProvider(有关详细信息,请参阅 Laravel 文档中的 注册事件和监听器)。

您可以使用 Laravel 的生成器为您创建监听器类,例如

artisan make:listener -e "\Cybex\Lodor\Events\FileUploaded" -- FileUploadedListener

然后将其包含在您的 EventServiceProvider $listener 属性中

use App\Listeners\FileUploadedListener;
use Cybex\Lodor\Events\FileUploaded;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        FileUploaded::class => [
            FileUploadedListener::class,
        ],
    ];

在您的 FileUploadedListener 类中,您应该在 handle() 方法中根据需要处理文件并触发 UploadFinished 事件,以指示您已完成处理,可以清理文件

    /**
     * Handle the event.
     *
     * @param  FileUploaded  $event
     * @return void
     */
    public function handle(FileUploaded $event)
    {
        $uuid     = $event->uuid;
        $metadata = $event->metadata;

        // You are also responsible to post updates on the status of the process using Lodor::setUploadStatus()
        // to keep the frontend up to date on the progress and any info you want to publish along with it.
        // After the server upload finishes, the upload is put in "waiting" state until the listener(s)
        // process(es) the upload and set the status to "done" state.
        Lodor::setUploadStatus($event->uuid,
            'done',
            __('Server upload finished.'),
            __('Upload complete.', ['uuid' => $uuid]),
            100,
            $metadata);

        // Then fire the UploadFinished event to signalize that the upload has completed processing.
        event(new UploadFinished($event->uuid, $event->metadata));
    }

手动清理

您也可以选择禁用 auto_cleanup 并自己进行清理。您可以通过执行上述步骤并在监听器的 handle() 方法中添加以下内容来实现

Lodor::cleanupUpload($event->uuid, true);

第二个参数指定是否强制删除所有文件,无论配置设置如何。

注意事项

有时,文件可能根本不会被清理,这可能是由于上传的缓存信息被删除、您的监听器崩溃或您使用队列事件监听器且作业队列失败或根本未运行。为了确保清理剩余文件,您可能需要定期计划一个 cron 作业,从 lodor_chunkedlodor_uploads 存储磁盘以及相应的缓存信息中删除旧文件。在 洛多 的未来版本中,计划实现监听器和 artisan 命令以定期清理。

测试

composer test

待办事项

  • 清理剩余上传的清理命令。

贡献

有关详细信息,请参阅 贡献

安全

如果您发现任何与安全相关的问题,请通过电子邮件 info@lupinitylabs.com 而不是使用问题跟踪器。

致谢

许可证

MIT 许可证(MIT)。请参阅 许可证文件 以获取更多信息。

Laravel 包模板

此包是使用 Laravel 包模板 生成的(感谢,Marcel!)。