• javascript原生态xhr上传多个图片,可预览和修改上传图片为固定尺寸比例,防恶意代码,加后端php处理图片


    //前端上传文件

    DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" lang="UTF-8">html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF-8;"/>
           
            <title>做上传文件测试用title>
           <script type="text/javascript" src="common.js">script>
    
           <style type="text/css">
            .button
            {
                margin-right: 20px;
            }
            #preview 
            {
                display: flex;
                flex-wrap: wrap;
                width: 800px;
                padding: 10px;
                justify-content: start;
            }
            .icon-po 
            {
                overflow: hidden;
                position: relative;
                width: 300px;
                height: 300px;
                margin-right: 20px;
                margin-top: 20px;
            }
    
            .icon-close 
            {
                position: absolute;
                right: 5%;
                top: 5%;
                width: 30px;
                border-radius: 50%;
                background-color: red;
                color: #fff;
                font-size: 12px;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .pic 
            {
                width:300px;
                height:300px;
            }
            style>
    
        head>
        <body>
        选择文件(可多选):<input type="file" id="f1" multiple/>
        <button type="button" class="button" id="btn-submit">预览图片button>
        <button type="button" id="complate">上传图片button>
        <div id="preview">div>
        <br/>
        <script type="text/javascript">
            var fL=[];
            //处理传过来的$_FIELS文件函数
            function previewUpdate(upfiles)
            {
            	//设置预览中添加的div1元素显示在前的顺序
                var e=0;
                //获取到预览容器preivew
                var preview=document.getElementById("preview");
                //如果$_FIELS大于0表示有文件过来
                if(upfiles.length>0)
                {
                    for(var i=0,len=upfiles.length;i<len;i++)
                    {
                      	//检测$_FILES的类型是否为图片
                        if(!/image\/(jpe?g|png|gif)/i.test(upfiles[i].type))
                        {
                        //如果不是则弹出文件名字提示
                            alert(upfiles[i].name+'不是图片');
                        }else
                        {
                        	//检测上传文件的大小是否小于1M
                            if(upfiles[i].size<1024*1000)
                            {
                            	//将上传的图片压入数组fL
                                fL.push(upfiles[i]);
                                
                            }else
                            {
                                alert('图片过大,请上传小于1M的图片');
                            }
                            
                        }
                        
                      
                    }
                  //循环出fL数组中的图片文件
                    fL.forEach(function(item,index,array){
                        //创建filereader()异步读取文件
                        var reader=new FileReader();
                        //创建预览容器div1和关闭按钮div2
                        var div1=document.createElement("div");
                            var div2=document.createElement("div");
                            //设置他们两的class类名,方便设置样式
                            div1.className="icon-po";
                            div2.className="icon-close";
                            //为div2设置关闭按钮文字X
                            div2.innerHTML='X';
                           //设置div1\div2显示的前后顺序
                            div1.index=div2.index=e;
                            //如果是多图为后面的图片准备顺序数字
                            e++;
                         //异步加载完成后添加图片对象和设置src的url   
                        reader.onload=function(event){
                            var img=new Image();
                            //设置图片样式
                            img.className="pic";
                            //设置读取到的url
                            img.src=reader.result;
                            //图片名字
                            img.title=item.name;
                            //将图片添加到div1中
                            div1.appendChild(img);
                            //将关闭按钮添加到div1中
                            div1.appendChild(div2);
                            //将图片div1小容器,添加到预览容器当中
                            preview.appendChild(div1);
                            //点击关闭按钮时,点击谁就关闭div1这个小容器图片,从preview这个大容器中删除这个子节点
                            div2.onclick=function(){
                                console.log(item);
                                div1.remove();
                                //在数组中将这个图片对象删除掉
                                fL.splice(index,1);
                                //console.log(fL);
                                
                            }
    
    
    
                        };
                        //读取每个图片对象
                        reader.readAsDataURL(item);
                    });   
                }else
                {
                    console.log('请选择文件 ');
                }    
                
            }
    	//将图片对象上传到服务器文件夹中
            function complateUpdate()
            {
            //创建xhr
                var xhr=new createXHR();
                
                //如果fL数组不为空,表示有图片
                if(fL.length>0)
                {
                    //创建formData()数据切片
                   var fd=new FormData();
                   //循环出数组当中的图片对象,必须用for in来循环,其它的循环会出错
                   //比如用for(var i=0,len=fL.length...)会有问题,也不能用foreach()
                   for(var files in fL)
                   {
                   //以files序列数字为名,将FL[files]添加到fd切片当中
                    fd.append(files,fL[files]);
                    //传输给后端
                    xhr.open("post","ajaxvalidationimg.php",true);
                    //发送切片数据
                    xhr.send(fd);
                    
                   }
                   
                  
                    //xhr加载完数据后事件
                    xhr.onload=function(){
                        
                            if((xhr.status>=200 && xhr.status<300)|| xhr.status==304)
                            {
                            //返回后端的数据
                                var arrtext=xhr.responseText;
                                //检测是否是json数据,如果不是则直接弹出信息
                                //如果是json数据则进行字符串切割,后割[]与[]之间的"\t\n",保存单个[]数据成数组
                                if(!/[\[\S*]]/.test(arrtext))
                                {
                                    alert(arrtext);
                                }else{
                                    var arrtext=arrtext.split("\t\n");
                                  //弹出不需要的空格组
                                    arrtext.pop();
                                    for(var g=0,leng=arrtext.length;g<leng;g++)
                                    {
                                    //解析后端的json数据成对象
                                        var a=JSON.parse(arrtext[g]);
                                        
                                       
                                    }
                                    //弹出对象中的信息
                                    alert(a.msg);
                                    //调用对象中的数据信息
                                    console.log(a.data);
                                }
                                
                                 
                            }else
                            {
                                console.log("接收数据发生错误");
                            }
                        
                    };
      
                }else
                {
                    alert('无图片');
                }
            }
    		//获取上传需要的三个元素按钮
            var button=document.getElementById('btn-submit');
            var upfiles=document.getElementById("f1");
            var upbutton=document.getElementById("complate");
            //如果选择图片按钮有变动则执行相应动作及函数
            upfiles.onchange=function(){
                previewUpdate(upfiles.files);
     
            }
            //预览窗口被点击展示和隐藏
            button.onclick=function(){
                var preview=document.getElementById("preview");
                var allStyle=document.defaultView.getComputedStyle(preview,null);
                if(allStyle.display!="none"){
                    preview.style.display="none";
                }else
                {
                    preview.style.display="flex";
                }
            };
            //上传按钮
            upbutton.onclick=function(){
                complateUpdate();
                //数组清空,防止重复提交
                fL=[];
                var preview=document.getElementById("preview");
                //清空已经上传的图片
                preview.innerHTML='';
              
            };
    
            
        script>
        body>   
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251

    //后端处理图片文件

    
    header("Content-Type:text/plain");
    //处理上传图片类
    class ValidationImg{
    //预设图片各种属性
       private $files=array(
            "name"=>'',
            'tmp_name'=>'',
            'size'=>'',
            "type"=>'',
            'error'=>''
        );
    	//最终上传的路径
        private $path='images/';
        //需要检查的图片类型白名单
        private $type=array('image/jpeg','image/jpg','image/png','image/gif');
        //图片属性字段
        private $fields=array();
        //保存上传后图片的各种属性
        private $init=array();
        //处理时需要的信息和完成后的数据数组
        public $message=array(
            'msg'=>'',
            'data'=>[]
            
        );
    	//构造函数,获取预设属性的键
        public function __construct()
        {
           $this->fields=array_keys($this->files);
        }
    	//处理上传的资源图片,将各属性保存进init数组中以备后续处理
        public function init($source)
        {
            
           if(is_array($source) && count($source)>0)
           {
            foreach($source as $key=>$val)
            {
                foreach($val as $k=>$v)
                {
                    foreach($this->fields as $default)
                    {
                        $this->init[$key][$k]=isset($source[$key][$default]) ?  $source[$key][$k] :$source[$key][$default];
                    }
                }
            }
           }else
           {
                $this->message['msg']='请上传图片';
                return false;
           }
          return $this->init;
        }
    	//获取资源图片的类型
        public function gettype()
        {
            foreach($this->init as $val)
            {
                if(in_array($val['type'],$this->type))
                {
                    return true;
                }else
                {
                    $this->message['msg']='图片类型不正确';
                }
            }
        }
    //创建空白图片以备后用
        public function newfiles()
        {
            foreach($this->init as $key=>$val)
            {
                $ext[$key]=trim(strrchr($val['name'],'.'),'.');
                $newfile[$key]=$this->path.strval(rand()).$ext[$key];
            }
            return $newfile;
        }
        //获取资源图片的后缀
        public function ext()
        {
            foreach($this->init as $key=>$val)
            {
                $ext[$key]=strrchr($val['name'],'.');
            }
            return $ext;
        }
    //获取资源图片的临时名字
        public function tmpfiles()
        {
            foreach($this->init as $key=>$val)
            {
                $tmpfile[$key]=$val['tmp_name'];
            }
            return $tmpfile;
        }
        //得到临时文件类型这个更准确,但这函数传有漏洞
        public function getimagesize()
        {
            foreach($this->init as $key=>$val)
            {
                $type[$key]=@getimagesize($val['tmp_name'])['mime'];
            }
            return $type;
        }
    //获取资源图片的大小
        public function getsize()
        {
            foreach($this->init as $key=>$val)
            {
                if($val['size']<1024*1000)
                {
                    $size[$key]=$val['size'];
                }else
                {
                    $this->message['msg']='图片太大,必须小于1M';
                    return false;
                }
            }
            return $size;
        }
    	//最终处理资源图片形成新的图片,并传数据给前端
        public function run()
        {
        	//先处理上传来的资源图片
            $f=$this->init($_FILES);
            //如果不为空时,且没有错误信息
            if(count($f)>0 && $this->message['msg']==='')
            {
    			//资源图片种类都正确时
                if($this->gettype()===true && $t= $this->getimagesize())
                {	
                	//资源图片大小正确时
                    if($this->getsize()!==false)
                    {
                        if(count($tmp=$this->tmpfiles())>0)
                        {
                        	//循环临时图片备用
                            foreach($tmp as $key=>$val)
                            {
                            	//循环新创建的空白图片备用
                                foreach($this->newfiles() as $k=>$v)
                                {
                                    //如果临时图片键=新创建空白图片键
                                    if($key==$k)
                                    {
                                        //将临时图片移动到新空白图片中
                                        if(move_uploaded_file($val,$v))
                                        {
                                           
                                           //检测图片类型,选择创建图片资源
                                            switch($t[$key])
                                            {
                                                
                                                case 'image/png': 
                                                    
                                                    $im=imagecreatefrompng($v);
                                                    break;
                                                case 'image/jpeg':
                                                    
                                                    $im=imagecreatefromjpeg($v);
                                                    break;
                                                case 'image/jpg':
                                                    
                                                    $im=imagecreatefromjpeg($v);
                                                    break;
                                                case 'image/gif':
                                                    
                                                    $im=imagecreatefromgif($v);
                                                    break; 
                                                case 'default': 
                                                    
                                                    $im=false;
                                                    break;               
                                            }
    										//如果$im=false表示,imagecratefromjpeg()等函数没能创建出图片
    										//表示临时文件移动到空白图片中是有问题的,表示用户上传的并不是图片类型
    										//有可能是修改了后缀上传的代码文件,所以$im为false
                                            if($im==false)
                                            {
                                                
                                                $this->message['msg']="只支持png,jpeg,gif,jpg图片格式,请勿上传其它类型文件";
                                                @unlink($v);
                                                
                                            }else
                                            {
                                                //新空白图片
                                                $img_path=$this->path.date('YmdHis').strval(rand()).$this->ext()[$key];
                                                //获取资源图片宽度
                                                $srcwidth=imagesx($im);
                                                //获取资源图片高度
                                                $srcheight=imagesy($im);
                                                //设置资源图片与我们设定宽度500值之间的比例保留后2位
                                                $wportion=number_format(($srcwidth/500),2);
                                                //获取资源图片宽/高的比例保留后2位
                                                $portion=number_format($srcwidth/$srcheight,2);
                                                //设置空白目标图片宽,资源图片宽 / 设定宽值比例值
                                                $dstwidth=ceil($srcwidth/$wportion);
                                                //设置空白目标图片高,目标图片宽度 / 资源图片宽高比例值
                                                $dstheight=ceil($dstwidth/$portion);
                                                if($srcwidth>500)
                                                {
                                                    //创建空白目标图片宽与高
                                                    $dst_image=imagecreatetruecolor($dstwidth,$dstheight);
                                                    //将资源图片按比例拷贝进目标空白图片当中
                                                    	imagecopyresampled($dst_image,$im,0,0,0,0,$dstwidth,$dstheight,$srcwidth,$srcheight);
                                                    //将拷贝的目标图片创建进我们设置的新空白地址图片当中,形成新图片,90为保留真色彩值
                                                    imagejpeg($dst_image,$img_path,90);
                                                    //删除创建的临时资源图片连接
                                                    @unlink($v);
                                                    //销毁目标图像相关联的所有内存
                                                    imagedestroy($dst_image);
                                                    //销毁临时图像句柄相关联的所有内存
                                                    imagedestroy($im);
                                                    $this->message['msg']='上传成功';
                                                    array_push($this->message['data'],$img_path);
                                                }else
                                                {
                                                    //将临时目标图片移进我们设置的新空白地址图片当中,形成新图片,90为保留真色彩值
                                                    imagejpeg($im,$img_path,90);
                                                    //删除创建的临时资源图片连接
                                                    @unlink($v);
                                                    //销毁临时图像句柄相关联的所有内存
                                                    imagedestroy($im);
                                                    
                                                    $this->message['msg']='上传成功';
                                                    array_push($this->message['data'],$img_path);
                                                }
    
                                            }
                                                $img=json_encode($this->message);
                                                echo $img;
                                                echo "\t\n";
                                            
                                        }else
                                        {
                                            $this->message['msg']="上传出错,请确保图片类型正确";
                                        }
                                    }
                                }
                            }
                        }else
                        {
                            echo '临时出错';
                        }
                    }
                    else
                    {
                        echo $this->message['msg'];
                    }
                }else
                {
                    echo $this->message['msg'];
                }
            }else
            {
                echo $this->message['msg'];
            }
        }
    
    
    }
    
    if(isset($_FILES)&& count($_FILES)>0)
    {
        $f=new ValidationImg();
       $v=$f->init($_FILES);
        print_r($f->run());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269

    //展示效果
    在这里插入图片描述

  • 相关阅读:
    解决javax.mail.MessagingException: Could not convert socket to TLS;
    C++学习笔记(Ⅰ):C++基础入门
    【机器学习】回归树生成过程及举例理解
    JMM内存模型
    人工智能时代:深入了解与学以致用的智能科技
    低代码平台 Power Platform 又上新,让你“事半功倍”
    C++入门——引用|内联函数|auto关键字|基于范围的for循环|指针空值
    大端模式与小端模式
    详解JS的四种异步解决方案:回调函数、Promise、Generator、async/await
    MySQL查询结果竖列转列为字段:深入探讨pivot操作与应用实践
  • 原文地址:https://blog.csdn.net/cdcdhj/article/details/134036345