zoukankan      html  css  js  c++  java
  • php大文件分片上传

    用过浏览器的开发人员都对大文件上传与下载比较困扰,之前遇到了一个php文件夹上传下载的问题,无奈之下自己开发了一套文件上传控件,在这里分享一下。希望能对你有所帮助。

     

    上传控件功能:

    1. 文件批量上传

    此文件管理器支持文件批量上传。您可以上传30G及以上的大型文件,在上传过程中您不需要担心刷新网页造成的进度丢失问题。也不需要担心浏览器重启或崩溃,电脑重启等极端应用场景造成的进度丢失问题。文件管理器能够自动定时保存文件上传进度。以便为您提供更好的用户体验。

    2. 文件夹批量上传

    此文件管理器提供文件夹的批量上传功能。您可以同时上传一个或者多个文件夹,文件管理器会将这些文件夹以及他们的结构信息同时保存在服务器中。您不需要担心浏览器重启或崩溃造成的进度丢失的问题。

    3. 文件批量下载

    此文件管理器提供了文件批量下载功能。您现在可以同时下载多个文件,并将他们保存在本地指定的目录中。这一功能为图库应用场景,多资料共享应用场景提供了使用便利。

    4. 文件夹批量下载

    此文件管理器提供了文件夹的批量下载功能。您可以同时下载多个文件夹,这些文件夹下载完毕后,他们的层级信息也将会同时在本地保留。

    5. 新建目录

    此文件管理器提供了多层级目录管理功能。您现在可以根据需求新建目录。

    6. 文件目录重命名。

    7. 树型目录导航

    8. 路径导航

    9. 开源

    此文件管理器是开款开源产品,无论您是个人还是企业都可以获取他的源代码来进行二次开发。我们为ASP.NET,JAVA,PHP等语言提供了示例,您可以同时选择这3种开发语言来进行项目开发。同时我们将提供长期的更新和维护服务,帮助企业节省后期的产品维护成本。

     

    以下是实例的部分脚本文件与文件块处理代码:

    //文件上传对象

    function FileUploader(fileLoc, mgr)

    {

        var _this = this;

        this.id = fileLoc.id;

        this.ui = { msg: null, process: null, percent: null, btn: { del: null, cancel: null,post:null,stop:null }, div: null};

        this.isFolder = false//不是文件夹

        this.app = mgr.app;

        this.Manager = mgr; //上传管理器指针

        this.event = mgr.event;

        this.FileListMgr = mgr.FileListMgr;//文件列表管理器

        this.Config = mgr.Config;

        this.fields = jQuery.extend({}, mgr.Config.Fields, fileLoc.fields);//每一个对象自带一个fields幅本

        this.State = this.Config.state.None;

        this.uid = this.fields.uid;

        this.fileSvr = {

              pid: ""

            , id: ""

            , pidRoot: ""

            , f_fdTask: false

            , f_fdChild: false

            , uid: 0

            , nameLoc: ""

            , nameSvr: ""

            , pathLoc: ""

            , pathSvr: ""

            , pathRel: ""

            , md5: ""

            , lenLoc: "0"

            , sizeLoc: ""

            , FilePos: "0"

            , lenSvr: "0"

            , perSvr: "0%"

            , complete: false

            , deleted: false

        };//json obj,服务器文件信息

        this.fileSvr = jQuery.extend(this.fileSvr, fileLoc);

     

        //准备

        this.Ready = function ()

        {

            this.ui.msg.text("正在上传队列中等待...");

            this.State = this.Config.state.Ready;

        };

     

        this.svr_error = function ()

        {

            alert("服务器返回信息为空,请检查服务器配置");

            this.ui.msg.text("向服务器发送MD5信息错误");

            this.ui.btn.cancel.text("续传");

        };

        this.svr_create = function (sv)

        {

            if (sv.value == null)

            {

                this.svr_error(); return;

            }

     

            var str = decodeURIComponent(sv.value);//

            this.fileSvr = JSON.parse(str);//

            //服务器已存在相同文件,且已上传完成

            if (this.fileSvr.complete)

            {

                this.post_complete_quick();

            } //服务器文件没有上传完成

            else

            {

                this.ui.process.css("width"this.fileSvr.perSvr);

                this.ui.percent.text(this.fileSvr.perSvr);

                this.post_file();

            }

        };

        this.svr_update = function () {

            if (this.fileSvr.lenSvr == 0) return;

            var param = { uid: this.fields["uid"], offset: this.fileSvr.lenSvr, lenSvr: this.fileSvr.lenSvr, perSvr: this.fileSvr.perSvr, id: this.id, time: new Date().getTime() };

            $.ajax({

                type: "GET"

                , dataType: 'jsonp'

                , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

                , url: this.Config["UrlProcess"]

                , data: param

                , success: function (msg) {}

                , error: function (req, txt, err) { alert("更新文件进度错误!" + req.responseText); }

                , complete: function (req, sta) { req = null; }

            });

        };

        this.post_process = function (json)

        {

            this.fileSvr.lenSvr = json.lenSvr;//保存上传进度

            this.fileSvr.perSvr = json.percent;

            this.ui.percent.text("("+json.percent+")");

            this.ui.process.css("width", json.percent);

            var str = json.lenPost + " " + json.speed + " " + json.time;

            this.ui.msg.text(str);

        };

        this.post_complete = function (json)

        {

            this.fileSvr.perSvr = "100%";

            this.fileSvr.complete = true;

            $.each(this.ui.btn, function (i, n)

            {

                n.hide();

            });

            this.ui.process.css("width""100%");

            this.ui.percent.text("(100%)");

            this.ui.msg.text("上传完成");

            this.Manager.arrFilesComplete.push(this);

            this.State = this.Config.state.Complete;

            //从上传列表中删除

            this.Manager.RemoveQueuePost(this.fileSvr.id);

            //从未上传列表中删除

            this.Manager.RemoveQueueWait(this.fileSvr.id);

     

            var param = { md5: this.fileSvr.md5, uid: this.uid, id: this.fileSvr.id, time: new Date().getTime() };

     

            $.ajax({

                type: "GET"

                 , dataType: 'jsonp'

                 , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

                 , url: _this.Config["UrlComplete"]

                 , data: param

                 , success: function (msg)

                 {

                     _this.event.fileComplete(_this);//触发事件

                     _this.FileListMgr.UploadComplete(_this.fileSvr);//添加到服务器文件列表

                     _this.post_next();

                 }

                 , error: function (req, txt, err) { alert("文件-向服务器发送Complete信息错误!" + req.responseText); }

                 , complete: function (req, sta) { req = null; }

            });

        };

        this.post_complete_quick = function ()

        {

            this.fileSvr.perSvr = "100%";

            this.fileSvr.complete = true;

            this.ui.btn.stop.hide();

            this.ui.process.css("width""100%");

            this.ui.percent.text("(100%)");

            this.ui.msg.text("服务器存在相同文件,快速上传成功。");

            this.Manager.arrFilesComplete.push(this);

            this.State = this.Config.state.Complete;

            //从上传列表中删除

            this.Manager.RemoveQueuePost(this.fileSvr.id);

            //从未上传列表中删除

            this.Manager.RemoveQueueWait(this.fileSvr.id);

            //添加到文件列表

            this.FileListMgr.UploadComplete(this.fileSvr);

            this.post_next();

            this.event.fileComplete(this);//触发事件

        };

        this.post_stoped = function (json)

        {

            this.ui.btn.post.show();

            this.ui.btn.del.show();

            this.ui.btn.cancel.hide();

            this.ui.btn.stop.hide();

            this.ui.msg.text("传输已停止....");

     

            if (this.Config.state.Ready == this.State)

            {

                this.Manager.RemoveQueue(this.fileSvr.id);

                this.post_next();

                return;

            }

            this.State = this.Config.state.Stop;

            //从上传列表中删除

            this.Manager.RemoveQueuePost(this.fileSvr.id);

            this.Manager.AppendQueueWait(this.fileSvr.id);//添加到未上传列表

            //传输下一个

            this.post_next();

        };

        this.post_error = function (json)

        {

            this.svr_update();

            this.ui.msg.text(this.Config.errCode[json.value]);

            this.ui.btn.stop.hide();

            this.ui.btn.post.show();

            this.ui.btn.del.show();

     

            this.State = this.Config.state.Error;

            //从上传列表中删除

            this.Manager.RemoveQueuePost(this.fileSvr.id);

            //添加到未上传列表

            this.Manager.AppendQueueWait(this.fileSvr.id);

            this.post_next();

        };

        this.md5_process = function (json)

        {

            var msg = "正在扫描本地文件,已完成:" + json.percent;

            this.ui.msg.text(msg);

        };

        this.md5_complete = function (json)

        {

            this.fileSvr.md5 = json.md5;

            this.ui.msg.text("MD5计算完毕,开始连接服务器...");

            this.event.md5Complete(this, json.md5);//biz event

     

            var loc_path = encodeURIComponent(this.fileSvr.pathLoc);

            var loc_len = this.fileSvr.lenLoc;

            var loc_size = this.fileSvr.sizeLoc;

            var param = jQuery.extend({}, this.fields, { md5: json.md5, id: this.fileSvr.id, lenLoc: loc_len, sizeLoc: loc_size, pathLoc: loc_path, time: new Date().getTime() });

     

            $.ajax({

                type: "GET"

                , dataType: 'jsonp'

                , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

                , url: this.Config["UrlCreate"]

                , data: param

                , success: function (sv)

                {

                    _this.svr_create(sv);

                }

                , error: function (req, txt, err)

                {

                    alert("向服务器发送MD5信息错误!" + req.responseText);

                    _this.ui.msg.text("向服务器发送MD5信息错误");

                    _this.ui.btn.del.text("续传");

                }

                , complete: function (req, sta) { req = null; }

            });

        };

        this.md5_error = function (json)

        {

            this.ui.msg.text(this.Config.errCode[json.value]);

            //文件大小超过限制,文件大小为0

            if ("4" == json.value

                 || "5" == json.value)

            {

            this.ui.btn.stop.hide();

            this.ui.btn.cancel.show();

            }

            else

            {           

                this.ui.btn.post.show();

                this.ui.btn.stop.hide();

            }

            this.State = this.Config.state.Error;

            //从上传列表中删除

            this.Manager.RemoveQueuePost(this.fileSvr.id);

            //添加到未上传列表

            this.Manager.AppendQueueWait(this.fileSvr.id);

     

            this.post_next();

        };

        this.post_next = function ()

        {

            var obj = this;

            setTimeout(function () { obj.Manager.PostNext(); }, 500);

        };

        this.post = function ()

        {

            this.Manager.AppendQueuePost(this.fileSvr.id);

            this.Manager.RemoveQueueWait(this.fileSvr.id);

            if (this.fileSvr.md5.length > 0)

            {

                this.post_file();

            }

            else

            {

                this.check_file();

            }

        };

        this.post_file = function ()

        {

            this.ui.btn.cancel.hide();

            this.ui.btn.stop.show();

            this.State = this.Config.state.Posting;//

            this.app.postFile({ id: this.fileSvr.id, pathLoc: this.fileSvr.pathLoc, pathSvr:this.fileSvr.pathSvr,lenSvr: this.fileSvr.lenSvr, fields: this.fields });

        };

        this.check_file = function ()

        {

            //this.ui.btn.cancel.text("停止").show();

            this.ui.btn.stop.show();

            this.ui.btn.cancel.hide();

            this.State = this.Config.state.MD5Working;

            this.app.checkFile({ id: this.fileSvr.id, pathLoc: this.fileSvr.pathLoc });

        };

        this.stop = function ()

        {

            this.ui.btn.del.hide();

            this.ui.btn.cancel.hide();

            this.ui.btn.stop.hide();

            this.ui.btn.post.hide();

            this.svr_update();

            this.app.stopFile({ id: this.fileSvr.id });       

        };

        //手动停止,一般在StopAll中调用

        this.stop_manual = function ()

        {

            if (this.Config.state.Posting == this.State)

            {

                this.svr_update();

            this.ui.btn.post.show();

            this.ui.btn.stop.hide();

            this.ui.btn.cancel.hide();

                this.ui.msg.text("传输已停止....");

                this.app.stopFile({ id: this.fileSvr.id ,tip:false});

                this.State = this.Config.state.Stop;

            }

        };

     

        //删除,一般在用户点击"删除"按钮时调用

        this.remove = function ()

        {

            this.Manager.del_file(this.fileSvr.id);

            this.app.delFile(this.fileSvr);

            this.ui.div.remove();

        };

    }

     

    <?php

    ob_start();

    /*

        控件每次向此文件POST数据

        逻辑:

             1.更新数据库进度

             2.将文件块数据保存到服务器中。

        更新记录:

             2014-04-09 增加文件块验证功能。

             2017-07-11

                 简化文件块逻辑,

                 取消进度更新操作

    */

    require '../vendor/autoload.php';

    require('biz/up6_biz_event.php');

    require('model/FileInf.php');

    require('utils/FileBlockWriter.php');

    require('utils/HttpHeader.php');

    require('utils/PathTool.php');

     

    use utilsFileBlockWriter;

     

    $head = new HttpHeader();

     

    $uid         = $head->param("uid");

    $fid         = $head->param("id");

    $md5         = $head->param("md5");

    $lenSvr           = $head->param("lenSvr");

    $lenLoc           = $head->param("lenLoc");

    $blockOffset = $head->param("blockOffset");

    $blockSize        = $head->param("blockSize");

    $blockIndex       = $head->param("blockIndex");

    $blockMd5         = $head->param("blockMd5");

    $complete         = (bool)$head->param("complete");

    $pathSvr     = $_POST["pathSvr"];

    $pathSvr     = PathTool::urldecode_path($pathSvr);

    $pathTmp     = $_FILES['file']['tmp_name'];//

     

    //相关参数不能为空

    if (   (strlen($lenLoc)>0)

        && (strlen($uid)>0)

        && (strlen($fid)>0)

        && (strlen($blockOffset)>0)

        && !empty($pathSvr))

    {

        $verify = false;

        $msg = "";

        $md5Svr = "";

       

        if(!empty($blockMd5))

        {

            $md5Svr = md5_file($pathTmp);

        }

       

        //验证大小

        $verify = intval($blockSize) == filesize($pathTmp);

        if( !$verify )

        {

            $msg = "block size error sizeSvr:" filesize($pathTmp) . " sizeLoc:" . $blockSize;

        }

       

        if( $verify && !empty($blockMd5) )

        {

             $verify = $md5Svr == $blockMd5;

             if(!$verify) $msg = "block md5 error";

        }

       

        if( $verify )

        {

             //保存文件块数据

             $fbw = new FileBlockWriter();

             if(0 == strcmp($blockIndex,"1")) $fbw->CreateFile($pathSvr,$lenLoc);

             $fbw->write($blockOffset, $lenLoc, $pathSvr, $pathTmp);

            

             up6_biz_event::file_post_block($fid, $blockIndex);

            

             $obj = Array('msg'=>'ok''md5'=>$md5Svr, 'offset'=>$blockOffset);

             $msg = json_encode($obj);

        }

        ob_clean();

        echo $msg;

    }

    else

    {

        echo "param is null";

        echo "uid:$uid<br/>";

        echo "fid:$fid<br/>";

        echo "md5:$md5<br/>";

        echo "lenSvr:$lenSvr<br/>";

        echo "lenLoc:$lenLoc<br/>";

        echo "f_pos:$blockOffset<br/>";

        echo "complete:$complete<br/>";

        echo "pathSvr:$pathSvr<br/>";

    }

    header('Content-Length: ' ob_get_length());

    ?>

    新建文件夹

    点击新建文件夹按钮,弹出此窗口,填写新建文件夹名称后点击确定

    页面左上角出现刚刚新建的文件夹名称

    粘贴上传

    复制文件夹、文件或图片

    在页面中选择好相应的上传目录,点击粘贴上传按钮,数据即可快速开始上传

     

    文件和文件夹批量上传上传功能,在新建文件夹目录内上传文件,选择多个文件或文件夹上传

    如果上传的是文件夹,那么左侧的文件夹内会自动添加一个子文件夹,与上传的文件夹相符并可以展开查看文件夹内文件

    在哪个目录下上传文件,文件就会存储在哪个目录下

     

    点击根目录按钮可以返回根目录

    当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。

     

    上传成功后打开我们的存储文件夹查看,发现自动生成了几个文件夹,打开文件夹确认上传文件成功

     

    点击文件夹后的重命名按钮

    修改文件名后点击确定

    页面左侧文件夹与页面中间的文件夹名称同时改变

     

    点击删除按钮

    点击确定后,页面中的文件消失

     

    文件下载

    部分下载脚本文件与代码:

    <?php

    require('../../db/database/DbHelper.php');

    require('../../db/utils/PathTool.php');

    require('../../db/model/FileInf.php');

    require('../model/DnFileInf.php');

    require('../biz/DnFile.php');

     

    $id      = $_GET["id"];

    $uid         = $_GET["uid"];

    $fdTask = $_GET["fdTask"];

    $nameLoc     = $_GET["nameLoc"];

    $pathLoc     = $_GET["pathLoc"];

    $lenSvr = $_GET["lenSvr"];

    $sizeSvr     = $_GET["sizeSvr"];

    $cbk         = $_GET["callback"];

    $pathLoc = PathTool::urldecode_path($pathLoc);

    $nameLoc = PathTool::urldecode_path($nameLoc);

    $sizeSvr = PathTool::urldecode_path($sizeSvr);

     

    if (  strlen($uid) < 1

        ||empty($pathLoc)

        ||empty($lenSvr))

    {

        echo cbk . "({"value":null})";

        die();

    }

     

    $inf = new DnFileInf();

    $inf->id = $id;

    $inf->uid = intval($uid);

    $inf->nameLoc = $nameLoc;

    $inf->pathLoc = $pathLoc;

    $inf->lenSvr = intval($lenSvr);

    $inf->sizeSvr = $sizeSvr;

    $inf->fdTask = $fdTask == "1";

     

    $db = new DnFile();

    $db->Add($inf);

     

    $json = json_encode($inf,JSON_UNESCAPED_SLASHESJSON_UNESCAPED_UNICODE);

    $json = urlencode($json);

    $json = "$cbk({"value":"".$json.""})";//返回jsonp格式数据。

    echo $json;

    ?>

     

    选择上传后的文件夹内的子目录文件或文件夹下载

     

    然后点击下载按钮,设置下载目录文件夹

    设置完成后继续点击下载按钮,页面的右下角出现了下载面板,你选择的文件已出现在目录中,然后点击全部下载,或者单个点击继续,自动加载未上传完的任务。在刷新浏览器或重启电脑后任然可以自动加载未完成的任务

     

    下载完成后打开我们设置的下载目录文件夹,发现需下载的文件或文件夹确认已下载成功,经确认文件夹内的内容与下载文件夹内容一致

    数据库记录

    说明: C:UsersAdministratorDesktopsql.png

     

    控件包下载:

    cab(x86):http://t.cn/Ai9pmG8S

    cab(x64): http://t.cn/Ai9pm04B

    xpi: http://t.cn/Ai9pubUc

    crx:http://t.cn/Ai9pmrcy

    exe:http://t.cn/Ai9puobe

     

    示例下载:

    asp.net: http://t.cn/Ai9pue4A

    jsp-eclipse: http://t.cn/Ai9p3LSx

    jsp-myeclipse:http://t.cn/Ai9p3IdC

    php:http://t.cn/Ai9p3CKQ

     

    在线文档:

    asp.net-测试教程:http://t.cn/Ai9pBM3A

    jsp测试教程:http://t.cn/Ai9pB82o

    php-测试教程:http://t.cn/Ai9prHik

  • 相关阅读:
    桟错误分析方法
    gstreamer调试命令
    sqlite的事务和锁,很透彻的讲解 【转】
    严重: Exception starting filter struts2 java.lang.NullPointerException (转载)
    eclipse 快捷键
    POJ 1099 Square Ice
    HDU 1013 Digital Roots
    HDU 1087 Super Jumping! Jumping! Jumping!(动态规划)
    HDU 1159 Common Subsequence
    HDU 1069 Monkey and Banana(动态规划)
  • 原文地址:https://www.cnblogs.com/xproer/p/10981090.html
Copyright © 2011-2022 走看看