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

news2024/9/20 22:37:20

//前端上传文件

<!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>

//后端处理图片文件

<?php
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());
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1132749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序通过获取键盘高度解决键盘弹出挡住输入框问题

我在这里写了个输入名称的头 在电脑上看着这输入效果还是挺优秀的 但当真的运行在手机上时 就会发现 这键盘一弹出来 就挡住我们的输入框了 这里 我们可以这样实现 在data中定义一个数值类型 叫 focusHeight 然后 给我们弹层 加上一个固定定位 然后 通过 focusHeight来控制…

【MySQL】用户与权限管理

文章目录 一、用户管理1、用户信息表2、创建用户3、删除用户4、修改用户密码 二、权限管理1、MySQL 权限2、给用户授权3、回收用户权限 一、用户管理 之前为了方便&#xff0c;我们学习 MySQL 时统一使用的都是 root 账号进行登录&#xff0c;但在实际的开发场景中必然是需要进…

基于SpringBoot的水果销售网站

基于SpringBootVue的水果销售网站系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven角色&#xff1a;管理员、商家、用户 系统展示 主页 水果详情 可直接购买&#xff0c;…

【Overload游戏引擎细节分析】standard材质Shader

提示&#xff1a;Shader属于GPU编程&#xff0c;难写难调试&#xff0c;阅读本文需有一定的OpenGL基础&#xff0c;可以写简单的Shader&#xff0c;不适合不会OpenGL的朋友 一、Blinn-Phong光照模型 Blinn-Phong光照模型&#xff0c;又称为Blinn-phong反射模型&#xff08;Bli…

鸡尾酒学习——长岛冰茶

长岛冰茶 1、材料&#xff1a;冰块&#xff08;或者雪莲&#xff09;、白朗姆、伏特加、龙舌兰、金酒、柠檬、君度或者白兰地、可乐&#xff1b; 2、口感&#xff1a;酸甜苦口味&#xff0c;酒的苦涩较为明显&#xff08;怀疑是自己放了过多的柠檬汁导致苦涩感明显&#xff09…

CrossOver 23.6 让Mac可以运行Windows程序的工具

在当今数字化时代&#xff0c;虚拟机技术被广泛应用于软件开发、系统测试、网络安全等领域。虚拟机提供了一个隔离的虚拟环境&#xff0c;使得我们能够在一台物理计算机上同时运行多个操作系统和应用程序。下面我们就来看虚拟机软件怎么安装&#xff0c;虚拟机怎么使用吧&#…

强制指定变量地址与局部优化

目录 一、强制编译器将变量分配到指定地址1. 编译器AC5.0与AC6.0有区别 二、 Keil/IAR局部优化1 IAR2.Keil AC5.03.Keil AC6.0 三 arm-none-eabi-gcc 下指定固定地址 一、强制编译器将变量分配到指定地址 1. 编译器AC5.0与AC6.0有区别 二、 Keil/IAR局部优化 1 IAR #pragma …

RTL SDR的PYTHON开发环境搭建

不得不说RTL SDR真是神器&#xff0c;直接把SDR的入门门槛拉低到了几十块钱。对于RTL SDR的学习开发&#xff0c;有大佬写的《Software_Defined_Radio_using_MATLAB_Simulink_and_the_RTL-SDR》&#xff0c;另外&#xff0c;除了MATLAB&#xff0c;近些年爆火的PYTHON当然也是可…

电厂数据可视化三维大屏展示平台加强企业安全防范

园区可视化大屏是一种新型的信息化手段&#xff0c;能够将园区内各项数据信息以图像的形式直观呈现在大屏幕上&#xff0c;便于管理员和员工进行实时监控、分析和决策。本文将从以下几个方面介绍园区可视化大屏的作用和应用。 VR数字孪生园区系统是通过将实际园区的各种数据和信…

2023年【起重信号司索工(建筑特殊工种)】试题及解析及起重信号司索工(建筑特殊工种)操作证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 起重信号司索工(建筑特殊工种)试题及解析根据新起重信号司索工(建筑特殊工种)考试大纲要求&#xff0c;安全生产模拟考试一点通将起重信号司索工(建筑特殊工种)模拟考试试题进行汇编&#xff0c;组成一套起重信号司索…

leetcode 503. 下一个更大元素 II、42. 接雨水

下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&…

EMC简述01

电磁兼容性&#xff08;EMC&#xff1a;Electromagnetic Compatibility&#xff09; 电磁兼容性&#xff08;EMC&#xff09;主要分为两种 一种是设备本身的电磁噪声对其他设备或人体带来的影响&#xff08;电磁干扰&#xff0c;EMI&#xff1a;Electromagnetic Interference…

我们在 Linux 环境中用 C 编程时,如果对文件读写,Linux 会自动给文件加锁嘛?以及怎么加文件锁?

task1: 验证Linux不会自动给文件加锁 先说结论&#xff0c;结论是不会 我写了一个这样的程序 #include <stdio.h> #include <unistd.h>int main() {const char* pathname "your_file_pathname.txt";FILE* file NULL;int count 100;if(access(pathn…

Linux 网络巨型帧设置方法

1.指令设置 sudo ifconfig eth0 mtu 8192 2.修改系统文件 sudo vim /etc/dhcp/dhclient.conf

Linux创建临时文件mkstemp()tmpfile()

有些程序需要创建一些临时文件&#xff0c;仅供其在运行期间使用&#xff0c;程序终止后即行删除。 很多编译器程序会在编译过程中创建临时文件。GNU C 语言函数库为此而提供了一系列库函数。&#xff08;之所以有“一系列”的库函数&#xff0c;部分原因是由于这些函数分别继…

opencalib中lidar2camera安装记录

目录 一、opencalib安装 二、lidar2camera的安装 三、测试运行 四、出现过的问题 一、opencalib安装 代码地址&#xff1a;https://github.com/PJLab-ADG/SensorsCalibration/blob/master/README.md # pull docker image sudo docker pull scllovewkf/opencalib:v1 # Aft…

DBOW概要理解与记录

前言 DBOW作为一种视觉回环技术被广泛应用在各类VSLAM框架中&#xff0c;之前的经验主要集中在使用和抽象理解层面&#xff0c;近期花了一些时间仔细阅读了相关论文和源码&#xff0c;这里做一些记录。 两个关键概念 Vocabulary 通过预先训练得到的词汇库&#xff0c;以树状…

RISC-V架构——中断委托和中断注入

1、中断委托 1.1、中断委托的作用 &#xff08;1&#xff09;默认情况下&#xff0c;所有的陷入&#xff08;中断和异常&#xff09;都是在M模式下处理&#xff0c;然后再返回到发生陷入前的模式&#xff1b; &#xff08;2&#xff09;所有陷入都在M模式处理会涉及到模式切换…

Python 面向对象编程:类、对象、初始化和方法详解

Python 是一种面向对象的编程语言。在 Python 中&#xff0c;几乎所有东西都是对象&#xff0c;都具有其属性和方法。 类似于对象构造函数或用于创建对象的“蓝图”的类。 创建一个类 要创建一个类&#xff0c;请使用关键字 class&#xff1a; 示例&#xff0c;创建一个名为…

【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b. 三角矩阵的压缩存储结构体初始化元素设置元素获取打印矩阵主函数输出结果代码整合 c. 对称矩阵的压缩存储元素设置元素获取主函数输出结果代码整合 4.2.1 矩阵的数组表示 【数据结构】数组和字…