AetherUpload - 让 Laravel 支持超大文件断点上传

说明

AetherUpload是提供超大文件上传的laravel扩展包,带百分比进度显示,支持断点续传,支持自定义中间件,基于laravel 5开发。

我们知道,在以前,文件上传采用的是直接传整个文件的方式,这种方式对付一些小文件是没有问题的。而当需要上传大文件时,此种方式不仅操作繁琐,需要修改web服务器和后端语言的配置,而且会大量占用服务器的内存,导致服务器内存吃紧,严重的甚至传输超时或文件过大无法上传。很显然,普通的文件上传方式已无法满足现在越来越高的要求。
随着技术的发展,如今我们可以利用HTML5的分块上传技术来轻松解决这个困扰,通过将大文件分割成小块逐个上传再拼合,来降低服务器内存的占用,突破服务器及后端语言配置中的上传大小限制,可上传任意大小的文件,同时也简化了操作,提供了直观的进度显示。

示例页面

用法

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

1) 在config/app.phpproviders数组中添加一行Peinhu\AetherUpload\AetherUploadServiceProvider::class,

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

3) 赋予上传目录相应权限,在项目根目录下,执行chmod 755 storage/app/uploads -R

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

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

优化建议

  • (推荐)设置每天自动清除无效文件。
    由于上传流程存在意外终止的情况,如在传输过程中强行关闭页面或浏览器,将会导致已产生的临时文件成为无效文件,占据大量的存储空间,我们可以使用Laravel的任务调度功能来定期清除它们。
    在Linux中运行crontab -e命令,确保文件中包含这行代码:
    * * * * * php /项目根目录的绝对路径/artisan schedule:run 1>> /dev/null 2>&1
    app/Console/Kernel.php中的schedule方法中添加以下代码:
    $schedule->call(function () {
      (new \Peinhu\AetherUpload\Uploader())->cleanUpDir();
    })->daily();
  • 提高临时文件读写速度。
    利用Linux的tmpfs文件系统,来达到将临时文件放到内存中快速读写的目的。执行以下命令:
    mkdir /dev/shm/tmp
    chmod 1777 /dev/shm/tmp
    mount --bind /dev/shm/tmp /tmp
本帖已被设为精华帖!
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 23
Summer

:+1: Cool

7年前 评论
baitongda

值得收藏一下

7年前 评论

我在上传的时候启用了秒传,已经提示了上传成功,但是服务器并没有文件,我试着将这段代码注释掉之后可以看到上传的文件,但是是 .part 后缀的

# 检测是否可以秒传
        if ( $fileHash ) {
            if ( RedisHandler::hashExists($fileHash) ) {
                $result['savedPath'] = RedisHandler::getFilePathByHash($fileHash); // file\201801\3178d162f252353a4ee625fd10703214.mp4
                return Responser::returnResult($result);
            }
        }

请问是问题出在哪里了呢?

6年前 评论

秒传一直没有走到 UploadHandler 里面的 saveChunk 方法

6年前 评论

重新安装了包,执行了 demo ,秒传虽然提示上传成功,但是服务器没有文件

6年前 评论

好吧,我加了一个配置项,在满足秒传的情况下,根据配置项决定是否启用秒传

config\aetherupload.php

<?php
return [
    .
    .
    .
    "OPEN_REDIS_UPLOAD"   => false,
];

vendor\peinhu\aetherupload-laravel\src

public static function hashExists($fileHash)
    {
        $result = false;

        if (config('aetherupload.OPEN_REDIS_UPLOAD')) {
            if ( class_exists('\Predis\Connection\ConnectionException') ) {
                try {
                    $result = Redis::hexists(config('aetherupload.REDIS_KEY'), $fileHash);
                } catch ( ConnectionException $e ) {

                }
            }
        }

        return $result;
    }
6年前 评论

@Kevinvinvin 晕,才看到这个,最好去github代码库那边反馈issue,一般能第一时间处理,这边是不能及时回复的?。
1)首先说一下秒传功能是不需要关闭选项的,设计逻辑是只要满足条件就能自动启用秒传,如果不满足条件就不启用,因为秒传本身只会带来好处,避免了文件重复造成的空间浪费,也节省了上传时间,所以没有必要关闭。
2)你的做法只是临时屏蔽了问题,但问题还是存在的,这么做秒传功能就没了,损失还是挺大的。
3)根据你的描述,说明插件判断文件已经存在,上传走了秒传流程,所以没有文件是正常的。原因的话我猜测可能是你手动删除了之前已上传的文件,但没有更新redis中的文件hash清单,产生了脏数据,即在你删除文件之后没有更新redis,redis中还留有该文件的hash记录,插件以为该文件是存在的,直接走秒传流程(不会上传文件)。如果是这种情况,可以通过执行php artisan aetherupload:build来重建redis中的文件hash清单,修正这个问题,然后以后的删除文件操作记得都需要及时更新redis。

6年前 评论

@Payne 搜嘎~ 恍然大悟 :sweat_smile::pray:

6年前 评论

想问一下 那个要用什么函数返回‘时长‘

5年前 评论

我想上传后缀名是exe的文件,但是我在源代码中发现了这个方法,哪位大神可以告诉我如何解决吗
file

并且我在配置文件的白名单设置了exe也没用

5年前 评论

此扩展已经无法使用,更新后报错

file

5年前 评论

@Cracker 你更新的什么版本?目前最新还是1.0.7,2.0版本还没正式发布。

5年前 评论

AetherUpload 2 已发布,根据用户反馈和需求,添加分布式部署支持、添加Mime-Type检查、添加头文件redis储存驱动、添加跨域中间件、添加秒传开关配置项、添加自定义黑名单配置项、代码重构优化。

5年前 评论
line75

有没有php接口类型的方案

4年前 评论

@line75 因为前端也是有一些特定逻辑的,所以如果是手机客户端不是直接可以用的,不过可以自己仿照着写一下。

4年前 评论

我是laravel5.8的,引入组件后,用组件中的示例可以上传文件,上传后也可以直接下载,就是使用组件提供的访问资源的访问去访问资源就会报404错误,我的nginx启用了伪静态,隐藏了index.php,如果我不隐藏index.php或者太访问资源的路径后再跟一个路径分隔符就可以访问到!请问一下如果使用伪静态,是不是还需要单独再配置什么?

4年前 评论

@xh2228609266 没遇到过这样的问题,刚用了5.8测试也无法复现问题,请用laravel文档中推荐的方法来做伪静态,应该不会有问题。一般来说,不会下载正常访问却不正常,如果你那边实在不行,那可以自己重写访问路由和处理逻辑。

4年前 评论

请问如何获取到上传文件的名称

4年前 评论

你好。有个问题请教一下

  1. 我想把上传的文件保存到项目根目录的 public 下
  2. 我想要获取到文件的上传的原来文件名

求大神赐教

4年前 评论

@xiaohui111
1.不可能直接传到/public,laravel规范是必须传到storage/app下的目录中,所以给出了storage:link这样的命令来把storage/app/public生成软连接到/public下。你想要本扩展上传的文件能在/public下访问,就要将配置文件中的root_dir对应项修改为'public',然后运行artisan命令aetherupload:groups,再运行storage:link,这样在/public就生成了软连接,就可以访问到文件了。
2.在前端可以获取到,通过上传完成回调success(someCallback)就可以获取到文件原名resourceName。

4年前 评论

请问一下,这个是断点续传还是断线续传?

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!