首页 > 其他分享 >webuploader实现大文件断点续传

webuploader实现大文件断点续传

时间:2023-11-17 10:15:01浏览次数:33  
标签:function 断点续传 文件 text app Yii fileMd5 webuploader chunk

前端代码(基于Yii框架,逻辑可供参考)

 

    <script>

        var fileMd5;  //文件MD5

        var fileObj;  //文件对象

        var state = 'pending';  //状态

        WebUploader.Uploader.register({

            "before-send": "beforeSend",

            "after-send-file": "afterSendFile"

        }, {

            beforeSend: function (block) {

                //每个分片开始上传前检查分片是否存在

                var deferred = WebUploader.Deferred();

                $.post('<?=Url::to(['video-upload/check-chunk'])?>', {

                    fileMd5: fileMd5,

                    chunk: block.chunk

                }, function (res) {

                    //不存在继续下一步

                    if (res.code == 1) {

                        deferred.resolve();

                    } else {

                        //已存在直接跳过

                        deferred.reject();

                    }

                }, 'json');

                //把fileMd5作为参数传入upload接口,配置项里无法直接配置所以放在这里

                this.owner.options.formData.fileMd5 = fileMd5;

                return deferred.promise();

            },

            afterSendFile: function () {

                $.post('<?=Url::to(['video-upload/merge-chunks'])?>', {

                    fileMd5: fileMd5,

                }, function (res) {

                    $('#videoupload-url').val(res.path);

                    $('#message').text(res.message);

                }, 'json');

            }

        });

 

        var uploader = new WebUploader.Uploader({

            // 自动上传。

            auto: false,

            // swf文件路径

            swf: '/webuploader/Uploader.swf',

            // 文件接收服务端。

            server: '<?=Url::to(['video-upload/upload'])?>',

            sendAsBinary: false,

            method: 'POST',

            pick: '#upload',

            // 只允许选择MP4文件

            accept: {

                extensions: 'mp4',

                mimeTypes: 'video/mp4'

            },

            resize: false,

            chunked: true,   //开启分片上传

            chunkSize: 2 * 1024 * 1024,   //分片大小2M

            threads: 1,

            //单个文件的大小 50M

            fileSingleSizeLimit: 50 * 1024 * 1024

        });

 

        uploader.on('fileQueued', function (file) {

            //计算文件的唯一标记fileMd5,用于断点续传  如果.md5File(file)方法里只写一个file参数则计算MD5值会很慢 所以加了后面的参数:50*1024*1024,此处的大小取决于配置中的fileSingleSizeLimit

            (new WebUploader.Uploader()).md5File(file, 0, 50 * 1024 * 1024).progress(function (percentage) {

            }).then(function (val) {

                $('#message').text("成功获取文件信息!");

                fileMd5 = val;

                //检查文件上传进度

                $.post('<?=Url::to(['video-upload/check-file'])?>', {

                    fileMd5: fileMd5,

                }, function (res) {

                    if (res.code === 200) {

                        $(".progress-bar").css('width', res.percent);

                        $(".progress-bar").text(res.percent);

                        if (res.percent == '0%') {

                            $("#btn").text('开始上传');

                        } else if (res.percent == '100%') {

                            $("#btn").text('上传完毕');

                        } else {

                            $("#btn").text('开始上传');

                        }

                    }

                }, 'json');

            });

            uploader.stop(true);

        });

 

        uploader.on('uploadProgress', function (file, percentage) {

            //动态更改上传进度

            var percent = Math.round(percentage * 100) + '%';

            $(".progress-bar").css('width', percent);

            $(".progress-bar").text(percent);

            $("#message").val('上传中...');

        });

 

        uploader.on('error', function (error) {

            //错误处理

            console.log(error);

            $("#btn").val('开始上传');

            uploader.stop(true);

            if (error == 'F_EXCEED_SIZE') {

                $('#message').text('文件最大限制为50M');

            } else {

                $('#message').text(error);

            }

        });

 

        uploader.on('all', function (type) {

            //实时监听上传状态

            if (type === 'startUpload') {

                state = 'uploading';

            } else if (type === 'stopUpload') {

                state = 'paused';

            } else if (type === 'uploadFinished') {

                state = 'done';

            } else if (type === 'fileQueued') {

                state = 'queued';

            }

 

            if (state === 'uploading') {

                $("#btn").text('暂停上传');

            } else if (state === 'paused') {

                $("#btn").text('继续上传');

            } else if (state === 'queued') {

                $("#btn").removeAttr('disabled');

            } else if (state === 'done') {

                $("#btn").text('上传完毕');

                $("#btn").attr('disabled', 'disabled');

            }

        });

 

        uploader.on('uploadSuccess', function (file, response) {

            $(".progress-bar").css('width', '100%');

            $(".progress-bar").text('100%');

            $("#btn").text('上传完毕');

            $("#btn").attr('disabled', 'disabled');

        });

 

        //手动操作视频上传/暂停/继续

        $("#btn").click(function () {

            if (state === 'uploading') {

                uploader.stop(true);

                return false;

            }

            uploader.upload(fileObj);

        });

    </script>

 

后端接口代码

 

/**

 * 分片上传

 * @return array

 */

public function actionUpload()

{

    if (Yii::$app->request->isPost) {

        Yii::$app->response->format = Response::FORMAT_JSON;

        $file = UploadedFile::getInstanceByName('file');

        $chunk = Yii::$app->request->post('chunk', 0);

        $fileMd5 = Yii::$app->request->post('fileMd5');

        $chunks = Yii::$app->request->post('chunks', 1);

        $percent = ((round(($chunk + 1) / $chunks, 2)) * 100) . '%';

        //记录该文件的上传进度

        Yii::$app->cache->set($fileMd5, $percent);

        //把分片内容按照一定规律存储

        rename($file->tempName, $this->tempFile($fileMd5, $chunk));

        return [

            'code' => 200,

            'message' => 'success',

        ];

    }

}

 

/**

 * 合并所有分片

 * @return array

 */

public function actionMergeChunks()

{

    $fileMd5 = Yii::$app->request->post('fileMd5');

    $full = $this->tempFile($fileMd5);

    $fp = fopen($full, 'wb');

    $i = 0;

    while (file_exists($this->tempFile($fileMd5, $i))) {

        $content = file_get_contents($this->tempFile($fileMd5, $i));

        fwrite($fp, $content);

        //删除分片

        unlink($this->tempFile($fileMd5, $i));

        $i++;

    }

    fclose($fp);

    Yii::$app->cache->delete($fileMd5);

    Yii::$app->response->format = Response::FORMAT_JSON;

    $data = [

        'code' => 200,

        'message' => 'success',

        'path' => '../upload/' . $fileMd5 . '.mp4',

    ];

    return $data;

}

 

/**

 * 分片上传前检查分片是否已存在

 */

public function actionCheckChunk()

{

    if (Yii::$app->request->isPost) {

        Yii::$app->response->format = Response::FORMAT_JSON;

        $fileMd5 = Yii::$app->request->post('fileMd5');

        $chunk = Yii::$app->request->post('chunk', 0);

        if (file_exists($this->tempFile($fileMd5, $chunk))) {

            return [

                'code' => 0,

                'message' => 'chunk_exists',

            ];

        } else {

            return [

                'code' => 1,

                'message' => 'chunk_not_exists',

            ];

        }

    }

}

 

/**

 * 开始上传前检查文件上传进度

 * @return array

 */

public function actionCheckFile()

{

    Yii::$app->response->format = Response::FORMAT_JSON;

    $fileMd5 = Yii::$app->request->post('fileMd5');

    $percent = Yii::$app->cache->get($fileMd5) ? Yii::$app->cache->get($fileMd5) : '0%';

    return [

        'code' => 200,

        'percent' => $percent,

    ];

}

 

/**

 * 获取格式化的文件名

 * @param $fileMd5

 * @param null $chunk

 * @return bool|string

 */

private function tempFile($fileMd5, $chunk = null)

{

    $tempFile = Yii::getAlias('@webroot/upload/' . $fileMd5);

    if (is_null($chunk)) {

        $tempFile .= '.mp4';

    } else {

        $tempFile .= '.chunk' . $chunk;

    }

    return $tempFile;

}

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/17/webuploader%e5%ae%9e%e7%8e%b0%e5%a4%a7%e6%96%87%e4%bb%b6%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

 

标签:function,断点续传,文件,text,app,Yii,fileMd5,webuploader,chunk
From: https://www.cnblogs.com/songsu/p/17838016.html

相关文章

  • 未预编译文件“/default.aspx”,因此不能请求该文件
    未预编译文件“/default.aspx”,因此不能请求该文件。说明:执行当前Web请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。异常详细信息:System.Web.HttpException:未预编译文件“/default.aspx”,因此不能请求该文件。 ......
  • 相机突然断电,保存的DAT视频文件如何修复
    3-7本文主要解决因相机突然断电导致拍摄的视频文件损坏的问题。在平常使用相机拍摄视频,比如用单反相机、无人机拍摄视频的时候,如果电池突然断电,或者突然炸机了,就非常有可能会得到一个损坏的视频文件,比如会产生下图中左边的这种文件,这种文件打不开,如果你是做生意的,比如搞婚庆拍摄的,......
  • 电脑版微信图片保存在哪个文件夹,如何一次性全选保存
     8-7电脑版的微信聊天,接收到图片后,会保存到微信的个人数据文件夹中,但是有个问题是这些图片都是加密保存的,普通情况下,确实无法人工去取出来,但是下面有方法可以快速将这些图片在脱离微信的情况下,批量取出来。首先是基础信息获取一、首页找到微信的个人数据文件夹,在电脑版微信登录后,......
  • VS Code中C开发多源文件的编译设置
    1.引言C开发中,通常需要编译多个文件,本文将简要介绍在VSCode中进行C开发时如何编译多个文件。实例工程结构如图所示:其中,main.c文件内容如下:#include"stdio.h"/*Includings*/#include"umath.h"#include"ucmplx.h"intmain(void){/*Testumath.c*/floa......
  • [EFI]Surface Pro 4电脑 Hackintosh 黑苹果引导文件
    硬件型号驱动情况主板SurfacePro4处理器IntelCorei5-6300U2.5GHz已驱动内存16GBDDR42400Mhz已驱动硬盘SamsungSSD860EVO250GMedia(InstallonSSDExternal)已驱动显卡IntelHDGraphics5202GBmacOS13以上自行添加显卡补丁声卡RealtekALC3269(id3)已驱动网卡无无无......
  • 网路文件共享服务
    网路文件共享服务存储类型直连式存储(DNS)网络附加存储(NAS)(存储和管理空间都在远程)(FTP,NFS)存储区域网络(SAN)(可以使用空间,管理也是你来管理)应用场景DNS:适用于数据量不大,对磁盘访问速度要求高的中小企业NAS:多适用于文件服务器,用来存储非结构化数据,虽然受限于以太网的速度,但是......
  • linux下使用命令行工具alidrive上传文件到阿里云盘
    linux下使用命令行工具alidrive上传文件到阿里云盘下载alidrive,并解压wgethttps://github.com/aoaostar/alidrive-uploader/releases/download/v2.2.1/alidrive_uploader_v2.2.1_linux_amd64.tar.gztar-xvfalidrive_uploader_v2.2.1_linux_amd64.tar.gz修改配置文件重......
  • vue2 项目打包后自动压缩成zip文件
    安装依赖1pnpminstallfilemanager-webpack-plugin--save-dev在vue.config.js中添加如下代码constFileManagerPlugin=require('filemanager-webpack-plugin')//引入插件1configureWebpack:{2plugins:[3newFileManagerPlugin({......
  • 反编译C#的dll文件并修改,再重新生成dll
    1、把dll文件导入到ildasm工具中,ildasm是由微软提供的.net程序反编译工具,位于“C:\ProgramFiles\MicrosoftSDKs\Windows\v6.0A\bin” 2、在ildasm中File->dump,把dll文件转储为*.il文件存到某个指定文件夹里,得到*.il和*.res两个文件,有时也会有*.resource文件 3、打开得到的......
  • C#反编译dll文件,修改其中汉字内容,再重新生成dll
    一位电气朋友让我帮其反编译一个dll文件,只要修改dll中部分中文字符串的内容(比如:‘电机编号’、‘接线方式’等等)。这样的事情自己从来还没接触过,能否实现、难度怎样也没一个概念,但为了帮他一下,也为了挑战下看自己到底需要多久才能解决此全新问题,欣然接受了。从9:16到1......