A Laravel package to upload large files

Overview

AetherUpload-Laravel

996.icu Build Status Latest Stable Version Total Downloads Latest Unstable Version License LICENSE

提供超大文件上传的Laravel扩展包,支持分组配置断线续传秒传分布式部署等功能,简单易用,满足多数人的主流需求。无感知化的设计理念,可实现由扩展自动接管上传和访问请求,开发者专注于业务,无需关心上传流程,无需编写适配代码,几乎开箱即用,节省大量开发时间。基于Laravel 5开发,支持5.1以上版本。

我们知道,在以前,文件上传采用的是直接传整个文件的方式,这种方式对付一些小文件是没有问题的。而当需要上传大文件时,此种方式不仅操作繁琐,需要修改web服务器和后端语言的配置,而且会大量占用服务器的内存,导致服务器内存吃紧,严重的甚至传输超时或文件过大无法上传。很显然,普通的文件上传方式已无法满足现在越来越高的要求。

随着技术的发展,如今我们可以利用HTML5的分块上传技术来轻松解决这个困扰,通过将大文件分割成小块逐个上传再拼合,来降低服务器内存的占用,突破服务器及后端语言配置中的上传大小限制,可上传任意大小的文件,同时也简化了操作,提供了直观的进度显示。

示例页面

功能特性

  • 百分比进度条
  • 文件类型限制
  • 文件大小限制
  • 多语言
  • 分组配置
  • 自定义中间件
  • 自定义路由
  • 上传完成事件
  • 同步上传
  • 断线续传
  • 文件秒传
  • 分布式部署

①:同步上传相比异步上传,在上传带宽足够大的情况下速度稍慢,但同步可在上传同时进行文件的拼合,而异步因文件块上传完成的先后顺序不确定,需要在所有文件块都完成时才能拼合,将会导致异步上传在接近完成时需等待较长时间。同步上传每次只有一个文件块在上传,在单位时间内占用服务器的内存较少,相比异步方式可支持更多人同时上传。

②:断线续传和断点续传不同,断线续传是指遇到断网或无线网络不稳定时,在不关闭页面的情况下,上传组件会定时自动重试,一旦网络恢复,文件会从未上传成功的那个文件块开始继续上传。断线续传在刷新页面或关闭后重开是无法续传的,之前上传的部分已成为无效文件。

③:文件秒传需服务端Redis和客户端浏览器支持(FileReader、File.slice()),两者缺一则秒传功能无法生效。默认关闭,需在配置文件中开启。

④:分布式部署需要在应用服务器与储存服务器进行跨域配置,通过填写相关配置项可实现自动跨域,并共享cookie和session。

用法

安装

0 在终端内切换到你的laravel项目根目录,执行composer require peinhu/aetherupload-laravel ~2.0

1 (Laravel 5.5+请跳过)在config/app.phpproviders数组中添加一行AetherUpload\AetherUploadServiceProvider::class,

2 执行php artisan aetherupload:publish来发布一些文件和目录

3 在浏览器访问http://域名/aetherupload可到达示例页面

提示:更改相关配置选项请编辑config/aetherupload.php

基本用法

文件上传:参考示例文件注释的部分,在需要上传大文件的页面引入相应文件和代码。可使用自定义中间件来对文件上传进行额外过滤,还可使用上传完成事件对上传的文件进一步处理。

分组配置:在配置文件的groups下新增分组,运行php artisan aetherupload:groups自动创建对应目录。

自定义中间件:参考laravel文档中间件部分,创建你的中间件并在Kernel.php中注册,将你注册的中间件名称填入配置文件对应部分,如['middleware1','middleware2']

上传完成事件:分为上传完成前和上传完成后事件,参考laravel文档事件系统部分,在EventServiceProvider中注册你的事件和监听器,运行php artisan event:generate生成事件和监听器,将你注册的事件完整类名填入配置文件对应部分,如'App\Events\OrderShipped'。

添加秒传功能(需Redis及浏览器支持)

安装Redis并启动服务端。安装predis包composer require predis/predis。确保上传页面引入了spark-md5.min.js文件。

提示:在Redis中维护了一份与实际资源文件对应的秒传清单,实际资源文件的增删造成的变化均需要同步到秒传清单中,否则会产生脏数据,扩展包已包含新增部分,当删除资源文件时,使用者需手动调用对应方法删除秒传清单中的记录。

\AetherUpload\Util::deleteResource($savedPath); //删除对应的资源文件
\AetherUpload\Util::deleteRedisSavedPath($savedPath); //删除对应的redis秒传记录

分布式部署(需Redis及域名跨域支持)

分布式部署通过将应用服务器与储存服务器分离,可减少应用服务器负载,增加应用并发连接数,降低耦合,减少单点故障风险,提高访问效率,启用分布式部署后应用服务器将不处理任何上传和访问请求。

安装Redis并启动服务端。安装predis包composer require predis/predis。确保上传页面表单中包含{{ storage_host_field() }}

应用服务器配置:
config/aetherupload.php中配置distributed_deployment项,将enable设置为truerole设置为webstorage_host设置为储存服务器的域名http://storage.your-domain.com
.env中将APP_NAMEAPP_KEY配置项改为对应特定值,与储存服务器配置一致。新增配置SESSION_DOMAIN=.your-domain.com,用以共享cookie。修改配置SESSION_DRIVER=redis,用以共享session。

储存服务器配置:
config/aetherupload.php中配置distributed_deployment项,将enable设置为truerole设置为storagemiddleware_cors设置为跨域中间件AetherUploadCORS类在Kernel.php中注册的名称,allow_origin设置为应用服务器的域名http://www.your-domain.com
.env中将APP_NAMEAPP_KEY配置项改为对应特定值,与应用服务器配置一致。新增配置SESSION_DOMAIN=.your-domain.com,用以共享cookie。修改配置SESSION_DRIVER=redis,用以共享session。

使用方便的artisan命令

php artisan aetherupload:groups 列出所有分组并自动创建对应目录
php artisan aetherupload:build 在Redis中重建资源文件的秒传清单
php artisan aetherupload:clean 2 清除2天前的无效临时文件
php artisan aetherupload:publish vendor:publish的简化命令,覆盖发布一些目录和文件

优化建议

  • (推荐)设置每天自动清除无效的临时文件。
    由于上传流程存在意外终止的情况,如在传输过程中强行关闭页面或浏览器,将会导致已产生的文件部分成为无效文件,占据大量的存储空间,我们可以使用Laravel的任务调度功能来定期清除它们。
    在Linux中运行crontab -e命令,确保文件中包含这行代码:
* * * * * php /项目根目录的绝对路径/artisan schedule:run 1>> /dev/null 2>&1  

app/Console/Kernel.php中的schedule方法中添加以下代码:

  $schedule->command('aetherupload:clean 2')->daily();
  • (推荐)提高头文件读写效率。
    通过将头文件的文件系统由本地硬盘改为Redis,提高头文件读写效率。
    config/aetherupload.php中将header_storage_disk项对应值改为redis
    config/filesystems.phpdisks项中添加redis配置:
    'disks' => [
        ...
        'redis' => [
           'driver' => 'redis',
           'disable_asserts'=>true,
        ],
        ...
    ]
  • 设置每天自动重建Redis中的秒传清单。
    不恰当的处理和某些极端情况可能使秒传清单中出现脏数据,从而影响到秒传功能的准确性,重建秒传清单可消除脏数据,恢复与实际资源文件的同步。
    在Linux中运行crontab -e命令,确保文件中包含这行代码:
* * * * * php /项目根目录的绝对路径/artisan schedule:run 1>> /dev/null 2>&1  

app/Console/Kernel.php中的schedule方法中添加以下代码:

  $schedule->command('aetherupload:build')->daily();
  • 提高分块临时文件读写速度(仅对PHP生效)。
    利用Linux的tmpfs文件系统,来达到将上传的分块临时文件放到内存中快速读写的目的,通过以空间换时间,提升读写效率,将会额外占用部分内存(约1个分块大小)。
    将php.ini中上传临时目录upload_tmp_dir项的值设置为"/dev/shm",重启fpm或apache服务。

  • 提高分块临时文件读写速度(对系统临时目录生效)。
    利用Linux的tmpfs文件系统,来达到将上传的分块临时文件放到内存中快速读写的目的,通过以空间换时间,提升读写效率,将会额外占用部分内存(约1个分块大小)。
    执行以下命令:
    mkdir /dev/shm/tmp
    chmod 1777 /dev/shm/tmp
    mount --bind /dev/shm/tmp /tmp

兼容性

IE Edge Firefox Chrome Safari
上传 10+ 12+ 3.6+ 6+ 5.1+
秒传 10+ 12+ 3.6+ 6+ 6+

安全性

AetherUpload在上传前使用白名单+黑名单的形式进行文件后缀名过滤,上传后再检查文件的Mime-Type类型。白名单直接限制了保存文件扩展名,黑名单默认屏蔽了常见的可执行文件扩展名,来阻止上传恶意文件,安全起见白名单一栏不应留空。

虽然做了诸多安全工作,但恶意文件上传是防不胜防的,建议正确设置上传目录权限,确保相关程序对资源文件没有执行权限。

更新日志

2021-01-04 v2.0.8
修复执行route:cache时可能报错的问题
增加mime-type错误警告
优化合并js文件

详见CHANGELOG.md

衍生项目

laravel-admin表单扩展:large-file-upload

许可证

使用GPLv2许可证及Anti 996许可证, 查看LICENCE文件及LICENSE_996文件以获得更多信息。

Comments
  • 上传exe文件显示错误的文件类型

    上传exe文件显示错误的文件类型

    源码中的'exe' 对应的是 'application/x-msdownload', 可是我在上传exe文件之后得到的exe对应的是application/x-dosexec 网上说application/x-dosexec是application/x-msdownload的子类,但是MimeType.php中的类型检测会返回null,导致上传exe文件失败

    opened by Sanbingduizhang 7
  • 上传后再次上传遇到的问题

    上传后再次上传遇到的问题

    测试环境:laravel 5.3,window10环境,apache服务器,chrome浏览器最新版 当第一次上传时,运行正常,但当同样的表单二次上传时,会出现加载文件后无响应的问题,在刷新后又恢复正常。 详细测试如下:首次上传路径为:http://app.xxxx.com/admin/programs/3/edit(为本地项目的编辑功能,域名为本地域名),编辑其他项目或上传新建其他项目,如访问路径http://app.xxxx.com/admin/programs/1/edit,均无法响应。但在刷新后,运行正常。 注:无响应时,浏览器控制台无报错。

    bug 
    opened by Dianwoung 7
  • 新手不明白怎么用

    新手不明白怎么用

    安装完之后按照步骤走能走到演示页面,但问题是演示里根本就没有后台上传逻辑呀? 第一次上传提示405错误,我就感觉肯定是没写路由造成的。然后仔细看了一下配置 发现默认有个路由:

    'route_preprocess' => '/aetherupload/preprocess', # 上传预处理的路由 'route_uploading' => '/aetherupload/uploading', # 上传文件分块的路由 'route_display' => '/aetherupload/display', # 文件展示的路由 'route_download' => '/aetherupload/download', # 文件下载的路由

    如果把这几个路由写到routes里,那对应的方法在哪?

    是需要自己写后端保存逻辑 还是我没明白怎么用? 如果自己写后台逻辑 那这个插件到底有什么用? 如果不用自己写 那保存文件方法怎么调用?

    opened by o531 6
  • 上传文件在服务器上一直报创建文件失败

    上传文件在服务器上一直报创建文件失败

    服务器及环境:centos-7.4.1708+php7.2+Nginx。 不论是改变存储路径还是官方默认路径(也就是啥不该,直接安装步骤操作),都一样错误。可是在本地ok,

    希望改进,动态存储路径,比如每个用户存储路径归类,比如用户1存1文件夹下,用户2存2文件夹下。我尝试在config的配置下改变路径,"UPLOAD_PATH" => public_path() . DIRECTORY_SEPARATOR . "Uploads" . DIRECTORY_SEPARATOR . "shops/".session('shopid')。哈哈,session问题来了

    question 
    opened by sheghai 6
  • 上传相同的文件,第一个文件上传正常,第二个相同的文件上传后会得到.part文件

    上传相同的文件,第一个文件上传正常,第二个相同的文件上传后会得到.part文件

    相同的图片文件上传二次 第一次正常上传,得到: 1fa20dee4af9958ac6cb4c7bd7d08061.jpg 类似这样的文件 第二次正常上传,得到:1628144614796819.jpg.part

    关闭了,'lax_mode' => true, 调用setLaxMode(true)方法,但问题依旧,仍然会得到一个.part,去掉part扩展名,上传的文件就是第一次正常上传的图片文件,字节大小一样

    bug 
    opened by kokobing 5
  • 关于创建目录,提个建议

    关于创建目录,提个建议

    按照你的文档,配置过后,能使用,但是当我想将文件存储目录更换时,遇到了两个问题。

    1.更换过后,我通过手动创建目录并赋予权限,上传图片时提示:“错误:无法创建文件”,发现是UploadHandler.php 第40行的**mkdir()**函数,没有第三个参数,导致目录无法创建(可能是目录太深了

    2.同上情况,发现目录下的_head文件夹也没有自动生成,然后在 Receiver.php 中的 getUploadHeadPath() 方法中添加了一个判断目录是否存在并创建目录的代码。

    我不知道这个是不是专门拿来提建议的,还是拿来解决问题的,如果有错还望给个更好的办法,新手。。 -.-

    opened by HimiHL 5
  • 上传tgz文件提示  错误:无效的文件类型

    上传tgz文件提示 错误:无效的文件类型

    调试代码发现是filterByExtension函数里面的 抛出异常 throw new \Exception(trans('aetherupload::messages.invalid_resource_type'));

    $extensions = ConfigMapper::get('resource_extensions');
    if ( empty($resourceExt) || (empty($extensions) === false && in_array($resourceExt, $extensions) === false) || in_array($resourceExt, ConfigMapper::get('forbidden_extensions')) === true ) {
         throw new \Exception(trans('aetherupload::messages.invalid_resource_type')); 
    }
    

    注释掉抛出异常后可以上传。 配置选项都是初始的 $extensions 为空 forbidden_extensions 中也没有 tgz. 按道理应该不会触发这个判断。各位有没有遇到这个情况?

    opened by xuncanzhe 4
  • 路由缓存(route:cache)会报错

    路由缓存(route:cache)会报错

    只要运行路由缓存命令,就会抛出以下错误:

    In Route.php line 880:
      Unable to prepare route [aetherupload] for serialization. Uses Closure.
    

    我觉得仅仅为了文件上传而牺牲整个网站打开速度是不太好的。就像捡了芝麻 丢了西瓜。强烈建议优化一下。

    question 
    opened by o531 4
  • 关于Hash的判断问题

    关于Hash的判断问题

    if ( ConfigMapper::get('lax_mode') === false && $resourceHash !== $resourceRealHash ) { throw new \Exception(trans('aetherupload::messages.upload_error')); } 很奇怪,为什么我上传文件一直在这个问题出错了 实际上我是直接复制例子的内容的

    opened by tdWarren 4
  • Pause and Cancel upload

    Pause and Cancel upload

    Pardon me because I don't speak chinese, I want to ask if this package support for pause/resume and canceling upload?

    Also whether it possible to upload file directly to Minio (or other Storage::disk) without the need of using temp folder in app/storage?

    Thanks

    opened by dels07 4
  • 动态配置上传目录的问题,又是我:)

    动态配置上传目录的问题,又是我:)

    需求:在多个控制器中,均需调用程序包,实现各个控制器上传指定目录的功能。 问题:在config目录下的aetherupload.php文件中,注释掉UPLOAD_FILE_DIR,在控制器中使用config(['aetherupload.UPLOAD_FILE_DIR'=>'example1']);动态配置该变量,但具体测试时发现文件上传到了根目录,并未上传到指定文件夹。是我调用方式不对,还是在控制器内配置参数变量无效?

    enhancement 
    opened by Dianwoung 4
  • 想问下关于UploadController里面的一个代码的问题

    想问下关于UploadController里面的一个代码的问题

         // validate the data in header file to avoid the errors when network issue occurs
            if ( (int)($partialResource->chunkIndex) !== (int)$chunkIndex - 1 ) {
                return Responser::returnResult($result);
            }
       就关于源码里面这段代码的情况,没太能理解这个判断的意思。所以就是实例化类中partialResource里面的chunkIndex和前端接受的index不一致的时候,是不需要报错的吗?
    
    opened by DaybreakY 4
  • 在LARAVEL9版本中存在无法使用秒传的问题。

    在LARAVEL9版本中存在无法使用秒传的问题。

    在LARAVEL9版本中存在无法使用秒传的问题,原因是League\Flysystem的版本问题。 在LARAVEL5版本中,使用League\Flysystem是1.0版本,在LARAVEL9版本中 League\Flysystem 使用的是3.0版本,所以像 use League\Flysystem\Adapter\AbstractAdapter; use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait; 就会报不存在, 在FLYSYSTEM3.X中也不存在Adapter这个目录。

    如果不使用秒传,则一切正常。不知道作者是否可以版本更新一下,或告知如何更改。

    opened by sunqj-sun 9
Releases(v2.0.8)
Owner
Payne
Payne
Laravel is accessible, powerful, and provides tools required for large, robust applications.

Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be trul

Web & Mobile | eCommerce | Full-Stack Developer 4 Nov 24, 2022
Validate your input data in a simple way, an easy way and right way. no framework required. For simple or large. project.

wepesi_validation this module will help to do your own input validation from http request POST or GET. INTEGRATION The integration is the simple thing

Boss 4 Dec 17, 2022
Stapler-based file upload package for the Laravel framework.

laravel-stapler Laravel-Stapler is a Stapler-based file upload package for the Laravel framework. It provides a full set of Laravel commands, a migrat

Code Sleeve 565 Dec 9, 2022
Stapler-based file upload package for the Laravel framework.

laravel-stapler Laravel-Stapler is a Stapler-based file upload package for the Laravel framework. It provides a full set of Laravel commands, a migrat

Code Sleeve 565 Dec 9, 2022
A laravel package to generate class files from stub files.

Laravel Stub Generator A php laravel package to generate useable php files from given stub files . Installation Require the package using composer: co

Touhidur Rahman 31 Dec 29, 2022
A Laravel package that allows you to use multiple ".env" files in a precedent manner. Use ".env" files per domain (multi-tentant)!

Laravel Multi ENVs Use multiple .envs files and have a chain of precedence for the environment variables in these different .envs files. Use the .env

Allyson Silva 48 Dec 29, 2022
Laravel Livewire Excel Upload with Progressbar

Laravel Livewire Excel Upload with Progressbar This is sample project, that explains how to import Excel files with progress bar Steps to run project

Prabakaran T 5 Oct 6, 2022
Laravel 9 Livewire Multiple Image Upload Example

Laravel livewire multiple image upload; Through this tutorial, i am going to show you how to upload multiple image using livewire in laravel apps.

Wesley Sinde 3 Feb 23, 2022
A package that uses blade templates to control how markdown is converted to HTML inside Laravel, as well as providing support for markdown files to Laravel views.

Install Install via composer. $ composer require olliecodes/laravel-etched-blade Once installed you'll want to publish the config. $ php artisan vendo

Ollie Codes 19 Jul 5, 2021
This package provides an integration with FFmpeg for Laravel. Laravel's Filesystem handles the storage of the files.

Laravel FFMpeg This package provides an integration with FFmpeg for Laravel 6.0 and higher. Laravel's Filesystem handles the storage of the files. Lau

Protone Media 1.3k Jan 1, 2023
Laravel-Mediable is a package for easily uploading and attaching media files to models with Laravel 5.

Laravel-Mediable Laravel-Mediable is a package for easily uploading and attaching media files to models with Laravel. Features Filesystem-driven appro

Plank Design 654 Dec 30, 2022
Laravel Package to generate CRUD Files using TALL Stack

tall-crud-generator Laravel Package to generate CRUD Files using TALL Stack Requirements Make sure that Livewire is installed properly on your project

AscSoftwares 75 Jan 2, 2023
A Laravel package for attachment files to models

Laravel attachmentable package A package for attachment files to models Installation Run the command below to add this package: composer require larav

Laravel Iran Community 4 Jan 18, 2022
Package to parse DNA kit files, and import them into Laravel

Package to parse DNA kit files, and import them into Laravel

Family Tree 365 4 Aug 31, 2022
Package for Laravel that gives artisan commands to setup and edit environment files.

Setup and work with .env files in Laravel from the command line NOTE: This doesn't work with Laravel 5 since .env files were changed. This is for Lara

Matt Brunt 6 Dec 17, 2022
Laravel 5 package for reading and writing CSV files.

CSV Laravel 5 package for reading and writing CSV files. Warning The package has been updated to PHP 7. If you can't update to PHP 7 use version 0.6.x

Maciej Wilgucki 48 Nov 29, 2022
This package provides a Logs page that allows you to view your Laravel log files in a simple UI

A simplistics log viewer for your Filament apps. This package provides a Logs page that allows you to view your Laravel log files in a simple UI. Inst

Ryan Chandler 9 Sep 17, 2022
Laravel Package - Files to S3 Like Cloud Storage

This is a Laravel package that handles and make easy the upload, overwrite, delete, cdn purge of files and directories on AWS S3 like cloud storages. It supports a form uploaded file (UploadedFile) or a base64 file string

André G. Inocenti Lobo Viana 3 Jun 17, 2022
Localization Helper - Package for convenient work with Laravel's localization features and fast language files generation

Localization Helper Package for convenient work with Laravel's localization features and fast language files generation. Installation Via Composer $ c

Galymzhan Begimov 0 Jul 13, 2019