大文件分片上传及MD5完整性验证:引用jquery.fcup.js

1、功能背景

  • 配置管理系统中,需通过web端实现设备的在线升级,此功能需在web页面实现升级包的上传。
  • 由于php.ini中的默认上传文件大小为2M,当php代码实现文件上传功能时,超过2M大小的文件无法直接上传,需调整php.ini中相关参数。
  • 修改php.ini中相关参数:
    file_uploads = On
    upload_max_filesize = 20M
    post_max_size = 20M
  • 当修改完参数重启系统后,上传文件仍是失效,无法实现。分析LAMP环境在设备上移植安装时,可能存在多份php.ini配置文件。需将多份配置文件中相关参数全部修改保存并重启才能生效。
  • 考虑到移植环境的复杂性及限制性,在线升级功能引入jquery.fcup.js插件,将大文件分片,实现升级包的上传及设备在线升级。

2、jquery.fcup.js

<script src="tpl/js/js/jquery.min.js"></script>
<script src="tpl/js/js/jquery.fcup.js"></script>
<script>

$.fcup({
    updom: '.fcup',//上传控件的位置dom		
	//upid: 'upid',//上传的文件表单id,有默认
	shardsize: '2',//切片大小,(单次上传最大值)单位M,默认2M
	upmaxsize : '1024',//上传文件大小,单位M,不设置不限制
	upstr: '文件上传',//按钮文字
	uploading: '上传中...',//上传中的提示文字
    upfinished: '长传完成',//上传完成后的提示文字
	upurl: 'update.php',//文件上传接口 node接口:http://127.0.0.1:8888/upload
	uptype: '<?php echo $file_type?>',//上传类型检测,用,号分割
    errmaxup: '长传文件过大',//检测文件是否超出设置上传大小
	errtype: '请重新上传<?php echo $file_type?>类型文件',//不支持类型的提示文字
	//接口返回结果回调
	upcallback : function(result){
        //console.log(result);
        var result=eval('('+result+')');
        //alert(result.msg);
        if (result.err != '0'){
            $.fcupStop('please upload again!');//终止运行,并且在按钮上显示内容
            alert(result.msg);
        }else{
            if(parseInt(result.index)>=parseInt(result.total)){//上传文件完成
                alert(result.msg);
            }
        }
	}
});
</script> 

3、结合jquery.fcup.js的业务逻辑,可实现分片大小及文件最大限制的动态限制

$file_type='zip';//上传压缩包类型
$max_size=15;//允许上传大小,单位	M
define(is_max_file,true);//是否大文件上传
$min_size=0.1;//切片文件大小,单位M
if(!is_max_file){
    $min_size=$max_size;
}
function alert($arr){
    if(!(isset($arr['index'])&&isset($res['total']))){
        if(!is_max_file){
            $arr['index']=$res['total']=1;
        }
    }
    if(is_max_file){
        $str='{';
        foreach($arr as $key=>$val){
            if($str!='{'){
                $str.=',';
            }
            $str.='"'.$key.'":'.'"'.$val.'"';
        }
        $str.='}';
        echo $str;
        exit;
    }
    echo '<script>alert("'.$arr['msg'].$arr['err'].'");</script>';
    if($arr['err']==0){
        echo '<script>location.href=location.href;</script>';
    }else{
        echo '<script>history.go(-1);</script>';
    }
    exit;
}
$post=strtolower($_SERVER['REQUEST_METHOD']);
if($post=='post'){
    $file='file';
    foreach( $_FILES as $key=>$val){
        $file=$key;
    }
    $file_name=isset($_POST['file_name']) ? $_POST['file_name'] :''; //大文件名称
    $file_name =is_max_file?$file_name:$_FILES[$file]['name'];
    $md5   = isset($_POST['file_md5']) ? $_POST['file_md5'] : 0; //文件的md5值
    $size  = isset($_POST['file_size']) ?  $_POST['file_size'] : null; //文件大小
    //$file_name=$_FILES[$file]['name'];
    if (!empty($_FILES[$file]['error'])) {
        switch($_FILES[$file]['error']){
            case '1':
                $error = '超过php.ini允许的大小。';
                break;
            case '2':
                $error = '超过表单允许的大小。';
                break;
            case '3':
                $error = '文件只有部分被上传。';
                break;
            case '4':
                $error = '请选择图片。';
                break;
            case '6':
                $error = '找不到临时目录。';
                break;
            case '7':
                $error = '写文件到硬盘出错。';
                break;
            case '8':
                $error = 'File upload stopped by extension。';
                break;
            case '9':
                $error = '上传文件错误。';
                break;
            case '999':
            default:
                $error = '未知错误。';
        }
        $res['msg']=$error;
        $res['err']=-1;
        alert($res);
    }
	//服务器上临时文件名
	$tmp_name = $_FILES[$file]['tmp_name'];
	if (!file_exists($tmp_name)) {
        $res['msg']="上传文件失败";
        $res['err']=-2;
        alert($res);
	}

	//判断升级文件是否存在
	if(file_exists("/var/www/update/")){
	    $res['msg']="正在升级中!请稍后...";
        $res['err']=-3;
        alert($res);
	}

    //判断升级文件名是否正确
    if($file_name != "update.zip"){
        $res['msg']="上传升级包文件名错误,请重新上传!";
        $res['err']=-9;
        alert($res);
    }

	$temp_arr = explode(".", $file_name);
	$file_ext = array_pop($temp_arr);
	$file_ext = trim($file_ext);
	$file_ext = strtolower($file_ext);
    //var_dump($temp_arr);

	if($file_ext!=$file_type){
        $res['msg']="文件类型错误,请上传".$file_type."压缩包";
        $res['err']=-1;
        alert($res);
	}

	//文件大小检查文件大小
	$file_size = $size;
	if ($file_size > $max_size*1024*1024) {
        $res['msg']="上传文件不能超过".$max_size."M";
        $res['err']=-1;
        alert($res);
	}

	//$save_path=dirname(__Dir__);
	$save_path=dirname(__Dir__).'/'. 'update.'.$file_type;//上传路径
	//	$oldfile_path =  iconv($save_path . 'web.zip','utf-8','GBK');
	$res['total']=isset($_POST['file_total']) ? $_POST['file_total']:0; //总片数
	$res['index']=isset($_POST['file_index']) ? $_POST['file_index']:0; //当前片数

	if($res['index']<=1){
	    if (file_exists($save_path)) {
	        @unlink($save_path);
	    }
	}//删除重传

    $content = file_get_contents($tmp_name);
    if (!file_put_contents($save_path, $content, FILE_APPEND)) {
        @unlink($tmp_name);
        $res['msg']="上传文件失败";
        $res['err']=-1;
        alert($res);
    }
    @unlink($tmp_name);
	$res['msg']="上传文件完成!";
    $res['err']=0;
    alert($res);

}//post结束

通过上述业务逻辑,可引用fcup.js并将其中的参数修改如下:
shardsize: ‘<?php echo $min_size?>’,//切片大小,(单次上传最大值)单位M,默认2M
upmaxsize : ‘<?php echo $max_size?>’,//上传文件大小,单位M,不设置不限制

4、升级包文件上传完成后,采用ajax实现升级包的完整性校验

  • 修改fcup.js的逻辑
$.fcup({
    updom: '.fcup',//上传控件的位置dom		
	//upid: 'upid',//上传的文件表单id,有默认
	shardsize: '<?php echo $min_size?>',//切片大小,(单次上传最大值)单位M,默认2M
	upmaxsize : '<?php echo $max_size?>',//上传文件大小,单位M,不设置不限制
	upstr: '上传升级包',//按钮文字
	uploading: '上传中...',//上传中的提示文字
    upfinished: '上传完成',//上传完成后的提示文字
	upurl: 'update.php',//文件上传接口 node接口:http://127.0.0.1:8888/upload
	uptype: '<?php echo $file_type?>',//上传类型检测,用,号分割
    errmaxup: '上传文件过大',//检测文件是否超出设置上传大小
	errtype: '请上传<?php echo $file_type?>文件',//不支持类型的提示文字
	//接口返回结果回调
	upcallback : function(result){
        // alert(result);
        //console.log(result);
        var result=eval('('+result+')');
        //alert(result.msg);
        if (result.err != '0'){
            $.fcupStop('重新上传');//终止运行,并且在按钮上显示内容
            alert(result.msg);
        }else{
            if(parseInt(result.index)>=parseInt(result.total)){//上传文件完成
                //alert(result.msg);
                document.getElementById("checkstate").style.display = "block";
                document.getElementById("checkstate").innerHTML = "升级包校验中请稍候......";
                document.getElementById("checkstate").style.color = "blue";
                updateGet();
                //loadProgress();
                //setInterval(loadProgress,1000);
            }
        }
	}
});
  • 前端逻辑js
function createXmlRequest()
{
    if(window.ActiveXObject) {
        var xmlHttps=["Microsoft.XMLHTTP","MSXML2.XMLHttp.5.0","MSXML2.XMLHttp4.0", "MSXML2.XMLHttp3.0","MSXML2.XMLHttp"];
        try  {
            for(var i=0;i<xmlHttps.length;i++) {
                var xmlHttp=new ActiveXObject(xmlHttps[i]);
                return xmlHttp;
            }
        } catch (error) { }
    } else  {
        var xmlHttp=new XMLHttpRequest();
        return xmlHttp;
    }
}
function ajaxget(xmlHttp, url) {
    xmlHttp.open("GET", url, true);//true为异步请求
    xmlHttp.setRequestHeader("If-Modified-Since", "0");//头部字段的名称和信息
    xmlHttp.send("");//send方法中的参数表示需要请求发送的数据
}

var xmlget1;
//对升级包进行解压缩并完整性校验,校验成功则下发升级命令至网关程序
function updateGet(){
    var url = "updateresult.php";
    xmlget1 = createXmlRequest();
    xmlget1.onreadystatechange = backUpdate;
    ajaxget(xmlget1, url);
}
function backUpdate(){
    if (xmlget1.readyState == 4) {
        if(xmlget1.status == 200){
            var res = xmlget1.responseText;
            if(res==1){
                //alert("升级包完整性校验成功!");
                document.getElementById("checkstate").innerHTML = "升级包校验成功!";
                document.getElementById("checkstate").style.color = "green";
                loadProgress();
            }else{
                //alert("升级包完整性校验失败!");
                document.getElementById("checkstate").innerHTML = "升级包校验失败!请重新上传!";
                document.getElementById("checkstate").style.color = "red";
            }
        }
    }
}
  • 后端校验updateresult.php
$resflag1 = 1;
$cmd = "unzip /var/www/update.zip -d /var/www/";
shell_exec($cmd);

if(file_exists("/var/www/update/filemd5.txt")){
    $oldmd51 = trim(@file_get_contents("/var/www/update/filemd5.txt"));
    $newmd51 = md5_file("/var/www/update/updated.zip");
    if($oldmd51 != $newmd51){
        $resflag1 = 0;
    }
}
if($resflag1){//校验成功
	//此处为具体的升级逻辑操作,如解压具体的升级包等
    echo "1";
}else{//校验失败
    $cmd = "rm /var/www/update.zip";
    shell_exec($cmd);
    $cmd = "rm -r /var/www/update";
    shell_exec($cmd);
    echo "0";
}


最后推荐一个公众号,一枚IT技术人成长路上关于生活和职场的思考,欢迎书友们前来交流和分享心得

在这里插入图片描述

福利~ 福利~ 福利~ 1块钱一次帮下CSDN资料

添加微信,备注下载资料~所需下载CSDN资料链接可通过微信发送。
在这里插入图片描述![在这里插入图片描述](https://img-blog.csdnimg.cn/20200907091119151.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZxX2ZseQ==,size_16,color_FFFFFF,t_70#pic_center

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值