Giter Site home page Giter Site logo

peinhu / aetherupload-laravel Goto Github PK

View Code? Open in Web Editor NEW
915.0 20.0 126.0 256 KB

A Laravel package to upload large files 上传大文件的Laravel扩展包

License: GNU General Public License v2.0

JavaScript 37.22% PHP 59.55% Blade 3.23%
upload big large files file laravel package

aetherupload-laravel's Introduction

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类型。白名单直接限制了保存文件扩展名,黑名单默认屏蔽了常见的可执行文件扩展名,来阻止上传恶意文件,安全起见白名单一栏不应留空。

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

更新日志

2023-08-16 v2.0.9
支持路由基础中间件,并添加相关配置选项
简化验证方法

详见CHANGELOG.md

衍生项目

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

许可证

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

aetherupload-laravel's People

Contributors

chanble avatar peinhu avatar remxcode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aetherupload-laravel's Issues

关于创建目录,提个建议

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

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

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

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

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

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

如何 使用oss 作为上传目录

我服务器 文件系统 是集成的阿里云oss laravel 用的 acobcyl/ali-oss-storage集成包
但是如果用这个上传 文件又回到了本地
上传目录 我看只能是 本地的绝对路径

建议

1.多文件上传
2.同一界面多个控件

最后 感谢作者

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

服务器及环境: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问题来了

如何解决很多分组问题?

比如用户需要将文件上传到自己的文件目录下,不同的目录,分组也不一样,分组太多无法每个都定义,此时上传配置是无效的,有什么方法可以解决这个问题?

请问如何上传exe的文件呢

image
我在源码中发现了这个方法,我在配置文件中设置FILE_EXTENSIONS => "exe" 也没有用,反正就是想上传exe后缀的文件

中间件验证用户登录

你好,我在配置文件中加入了验证用户是否登录的中间件

发现打印 \Auth::user() 输出为null

然后在 UploadHandler 的 preprocess 和 saveChunk 中打印用户变量仍为null

所以,我无法验证调用该接口时,用户是否已经登录

查看了一下,cookie中laravel_session是和页面用的同一个

请问怎样解决呢,谢谢

如何进行优化

已经按照你的优化建议每日进行清理垃圾文件,还有提高临时文件读写速度的方法了,可是上传速度还是很慢,有什么其他优化的方法么?

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

不同分组下的秒传问题

例如有两个分组:img与video , 首先向img中传入a.txt , 返回的savePath是img , 当再次向video传入一样的a.txt ,直接秒传了,返回的savePath还是img ,如何解决这个问题?

php artisan 错误如何处理

laravel 版本5.2
2 执行php artisan aetherupload:publish来发布一些文件和目录
用的是php artisan vendor:publish

分组配置:在配置文件的GROUPS下新增分组,运行php artisan aetherupload:groups自动创建对应目录。
[Symfony\Component\Console\Exception\CommandNotFoundException]
There are no commands defined in the "aetherupload" namespace.

兼容php5.6?

vendor/peinhu/aetherupload-laravel/src/MimeType.php:825

三元运算符:??

今天发现个问题...

服务器及环境:centos-7.4.1708+php7.2+Nginx。吓上传后结果如下:
执行回调 - 文件原名:store_0709114622.apk | 文件大小:8.34MB | 文件储存名:1b85c078d04bff0189f428bd39bf5e9c.apk

在本地上传(phpStudy集成环境)如下:
执行回调 - 文件原名:store_0709114622.apk | 文件大小:8.34MB | 文件储存名:apk\201807\1b85c078d04bff0189f428bd39bf5e9c.apk

居然文件储存名不对

返回路径不能把UPLOAD_PATH一起返回吗?

上传文件一直返回一个很久之前的旧文件地址

/201709/8c73b5cc9d00291507d309355829014b.xlsx for reading! File does not exist.
这个目录已经删除,改成固定的文件夹了。但是上传后返回的是这么个地址?
还有配置文件使用date 时区没有定义的问题

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

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

自定义上传路径, 比如日期格式

请问, 在现有的方案下如何做到, 根据上传文件的时间自动创建文件夹?

比如: 今天是 2017年1月12日 , 我上传了文件, 之后格式为
/home/app/storage/app/uploads/aetherupload_file/20170112/*.jpg

路由找不到问题

composer 安装完这个包后,我在routes目录下,无论是web.php,还是api新定义的路由,框架都找不到控制器和方法,会抛出notfoundexception异常, 一开始不知道是哪里出了问题,后来用composer 把这个包卸载了,框架就立马找到控制器了,代码就运行正常了,重复安装几次都能复现这个问题,我的环境是laravel5.7,希望作者告知原因。

请问分布式上传文件怎么做到?

现在我这里有一个场景:
大文件分片上传,等文件上传完成后再合并,现在由于我们的机器有两台,所以不同的小文件会随机上传到两台服务器上,这就给文件合并带来了问题 所以针对这种情况你们有好的解决方案没

建议前端js换个目录

现在publish以后拷贝到前端的目录是public/js/xxx.js
这个在5.5以后默认是忽略的目录,对代码发布测试不友好,建议换为更规范一点的public/vendor/aetherupload/js/xxx.js
的路径,下次git添加以后就不会变了。

分布式部署对于不同Laravel版本可能会报错

今天测试时注意到启用分布式部署后报错了,排查后发现原因是Laravel 5.6.30版本开始更改了EncryptCookies中间件的默认设定,据说是为了提升程序安全。

也就是说,你的应用服务器和储存服务器的Laravel版本应该都<5.6.30,或者都>=5.6.30,如果一个小于一个大于等于,那就会报错。

遇到以上原因报错,在5.6.30以上版本的EncryptCookies中间件中添加protected static $serialize = true;,可以解决这个问题。

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

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

文件上传后无法下载,数据损坏

你好,这个 package 我在5.4版本中试了下,的确实现了文件上传,当我用 response()->download() 下载的时候数据就损坏了,涉及的格式有 zip jpg等。难道是我的使用姿势不对?望回复,谢谢...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.