文件上传组件WebUploader使用详解2(MD5秒传、判断是否已经上传过)jquery

/ / 2020-07-28   阅读:2497
文件上传组件WebUploader使用详解2(MD5秒传、判断是否已经上传过)...
    文件秒传的实现原理其实就是在文件上传前,把内容读取出来,算出 md5 值,然后通过 ajax 与服务端进行验证, 然后根据结果选择继续上传还是跳过上传。

    由于这个验证行为是异步的,所以这里我们要借助 WebUploader 提供的 hook(WebUploader.Uploader.register)来实现。即在上传前的 hanlder 里面返回一个 promise 对象,这样 WebUploader 就会等待此过程,监听此 promise 的完成事件,自动继续。

1,效果图
(1)当我们选择文件后,会自动计算该文件的 md5 值(如果文件太大,需要等待一会儿,同时会有计算进度显示)


(2)当第一次上次时,效果同以前一样,正常上传。


(3)如果服务器已存在该文件,点击上传时,客户端这边会立刻弹出提示,且任务变成已完成(不再上传)


2,样例代码
(1)客户端代码(index.html)
高亮部分代码为在前文基础上新增的部分,即 MD5 验证的相关代码。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <!--引入CSS-->
    <link rel="stylesheet" type="text/css" href="webuploader/webuploader.css">
    <!--引入JS-->
    <script type="text/javascript" src="js/jquery-1.11.1.js"></script>
    <script type="text/javascript" src="webuploader/webuploader.js"></script>
    <script type="text/javascript">
      $(function() {
        //开始上传按钮
        var $btn = $('#ctlBtn');
        //文件信息显示区域
        var $list = $('#thelist');
        //当前状态
        var state = 'pending';
        //待上传文件的md5值(key为file id)
        var md5 = {};
 
        // WebUploader提供的钩子(hook),在文件上传前先判断服务是否已存在这个文件
        WebUploader.Uploader.register({
          'before-send-file': 'beforeSendFile' //整个文件上传前
        }, {
          beforeSendFile: function( file ) {
            var that = this;
            var deferred = WebUploader.Deferred();
            //上传前请求服务端,判断文件是否已经上传过
            $.post("http://www.hangge.com/checkFileExist.php", { md5: md5[file.id] },
            function(data){
              if (data == '1') {
                //跳过如果存在则跳过
                that.owner.skipFile( file );
                alert("文件已存在,无需上传!");
              }
              // 继续后面行为
              deferred.resolve();
            });
            return deferred.promise();
          }
        });
 
        //初始化Web Uploader
        var uploader = WebUploader.create({
            // swf文件路径
            swf: 'webuploader/Uploader.swf',
            // 文件接收服务端。
            server: 'http://www.hangge.com/upload.php',
            // 选择文件的按钮。可选。
            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: '#picker'
        });
 
        // 当有文件被添加进队列的时候(选择文件后调用)
        uploader.on( 'fileQueued', function( file ) {
          $list.append( '<div id="' + file.id + '" class="item">' +
              '<h4 class="info">' + file.name + '</h4>' +
              '<p class="md5"></p>' +
              '<p class="state"></p>' +
          '</div>' );
          //获取文件MD5值
          md5[file.id] = '';
          uploader.md5File( file )// 及时显示进度
            .progress(function(percentage) {
              $( '#'+file.id ).find('.md5').text('读取文件:'+parseInt(percentage*100)+"%");
            })
            // 完成
            .then(function(val) {
              md5[file.id] = val;
              $( '#'+file.id ).find('.md5').text('md5值:' + val);
              $( '#'+file.id ).find('.state').text('等待上传...');
            });
        });
 
        // 文件上传过程中创建进度条实时显示。
        uploader.on( 'uploadProgress', function( file, percentage ) {
            var $li = $( '#'+file.id );
            $li.find('p.state').text('上传中(' + parseInt(percentage * 100) + '%)');
        });
 
        // 文件上传成功后会调用
        uploader.on( 'uploadSuccess', function( file ) {
            $( '#'+file.id ).find('p.state').text('已上传');
        });
 
        // 文件上传失败后会调用
        uploader.on( 'uploadError', function( file ) {
            $( '#'+file.id ).find('p.state').text('上传出错');
        });
 
        // 文件上传完毕后会调用(不管成功还是失败)
        uploader.on( 'uploadComplete', function( file ) {
            $( '#'+file.id ).find('.progress').fadeOut();
        });
 
        // all事件(所有的事件触发都会响应到)
        uploader.on( 'all', function( type ) {
            if ( type === 'startUpload' ) {
                state = 'uploading';
            } else if ( type === 'stopUpload' ) {
                state = 'paused';
            } else if ( type === 'uploadFinished' ) {
                state = 'done';
            }
 
            if ( state === 'uploading' ) {
                $btn.text('暂停上传');
            } else {
                $btn.text('开始上传');
            }
        });
 
        // 开始上传按钮点击事件响应
        $btn.on( 'click', function() {
            if ( state === 'uploading' ) {
                uploader.stop();
            } else {
                // 不存在则上传文件
                uploader.upload();
            }
        });
      });
    </script>
    <style>
      #picker {
        display: inline-block;
      }
      #ctlBtn {
        position: relative;
        display: inline-block;
        cursor: pointer;
        background: #EFEFEF;
        padding: 10px 15px;
        color: #2E2E2E;
        text-align: center;
        border-radius: 3px;
        overflow: hidden;
      }
      #ctlBtn:hover {
        background: #DDDDDD;
      }
    </style>
  </head>
  <body>
    <div id="uploader" class="wu-example">
        <div class="btns">
            <div id="picker">选择文件</div>
            <div id="ctlBtn" class="webuploader-upload">开始上传</div>
        </div>
        <!--用来存放文件信息-->
        <div id="thelist" class="uploader-list"></div>
    </div>
  </body>
</html>

(2)服务端验证代码(checkFileExist.php)
其内部逻辑是遍历文件夹下所有文件,计算出 md5 值,并与提交的 md5 做比较。如果有相同的话则表示存在。
<?php
  //获取需要验证的md5值
  $md5 = $_POST["md5"];
  //验证结果
  $exist = 0;
  //切换目录
  chdir($_SERVER["DOCUMENT_ROOT"]."/uploadFiles/");
  //遍历该目录下的所有文件
  foreach(glob('*.*') as $filename) {
    //计算每个文件的md5值并判读
    if (strcmp($md5, md5_file($filename)) == 0){
      $exist = 1;
      break;
    }
  }
  echo $exist
?>

(3)服务端文件上传代码(upload.php)
这个与前文相比没有变化,具体见:文件上传组件WebUploader使用详解1(带进度的文件上传)

我要评论

昵称:
验证码:

最新评论

共0条 共0页 10条/页 首页 上一页 下一页 尾页
意见反馈