The javascript front-end xhr uses the FormData() and FileReader() functions to upload images, and the back-end php receives and processes the FormData() uploaded data. Only 1 data can be received and methods to prevent upload vulnerabilities.

//The front-end check type is simple check, because penetration will stop the front-end javascript code, so detection and replacement on the back-end is the focus.

<!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>For testing uploaded files</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>
    Select files (multiple selections possible): <input type="file" id="f1" multiple/>
    <button type="button" class="button" id="btn-submit">Preview image</button>
    <button type="button" id="complate">Upload pictures</button>
    <div id="preview"></div>
    <br/>
    <script type="text/javascript">
        var fL=[];
        //Create and obtain images and preview images
        function previewUpdate(upfiles)
        {<!-- -->
            var e=0;
            
            var preview=document.getElementById("preview");
            if(upfiles.length>0)
            {<!-- -->
                for(var i=0,len=upfiles.length;i<len;i + + )
                {<!-- -->
                   //Simple check whether it is an image type
                    if(!/image\/(jpe?g|png|gif)/i.test(upfiles[i].type))
                    {<!-- -->
                        alert(upfiles[i].name + 'Not a picture');
                    }else
                    {<!-- -->
                    //The uploaded image cannot be larger than 1M
                        if(upfiles[i].size<1024*1000)
                        {<!-- -->
                        //Finally, they are pushed into the fL array for subsequent program calls.
                            fL.push(upfiles[i]);
                            
                        }else
                        {<!-- -->
                            alert('The picture is too large, please upload a picture smaller than 1M');
                        }
                        
                    }
                    /*The direct input here is for back-end testing and can be deleted.
                   //Give directly to the array
                   fL.push(upfiles[i]);
                   */
                }
              //Loop through the picture objects in the array
                fL.forEach(function(item,index,array){<!-- -->
                    //Create FileReader() to read the picture object
                    var reader=new FileReader();
                    //Create a container and close button for the preview image. div1 is the container for the image, and div2 is for closing a single div1 container.
                    var div1=document.createElement("div");
                        var div2=document.createElement("div");
                        div1.className="icon-po";
                        div2.className="icon-close";
                        div2.innerHTML='X';
                       //Set the display order for each container and close button
                        div1.index=div2.index=e;
                        e++;
                      //reader.onload creates an image object after reading is completed and adds it to the div1 container
                    reader.onload=function(event){<!-- -->
                        var img=new Image();
                        img.className="pic";
                        //Get the URL connection of the image for easy preview
                        img.src=reader.result;
                        img.title=item.name;
                        div1.appendChild(img);
                        div1.appendChild(div2);
                        preview.appendChild(div1);
                        //Click the close button div2 to delete the subsection of div1
                        div2.onclick=function(){<!-- -->
                            console.log(item);
                            div1.remove();
                            //Also delete the corresponding value of the div1 container image object in the fL array
                            fL.splice(index,1);
                            //console.log(fL);
                            
                        }



                    };
                    //Read each image object in the array
                    reader.readAsDataURL(item);
                });
            }else
            {<!-- -->
                console.log('Please select a file');
            }
            
        }
//Upload image function
        function complateUpdate()
        {<!-- -->
        //Create xhr object
            var xhr=new createXHR();
            
            //Determine whether the array is not empty
            if(fL.length>0)
            {<!-- -->
                //Create formdata()
               var fd=new FormData();
               //Note: You must use for in here to add the picture object in fL to fd, which is equivalent to looping out the object.
               //Cannot use for(var i=0,len=fL.length;i<len;i + +) loop
               //Or fl.forEach(), if you use these methods to pass pictures, the backend can only receive the last one.
               
               for(var files in fL)
               {<!-- -->
               //files represents the key in fL, which is generally a natural number. fL[files] is the image object in the array.
                fd.append(files,fL[files]);
                xhr.open("post","ajax.php",true);
                xhr.send(fd);
                
               }
               
              
                //The event triggered when xhr.onload is loaded is the callback data transmitted from the backend
                xhr.onload=function(){<!-- -->
                    
                        if((xhr.status>=200 & amp; & amp; xhr.status<300)|| xhr.status==304)
                        {<!-- -->
                            alert(xhr.responseText);
                        }else
                        {<!-- -->
                            console.log("An error occurred while receiving data");
                        }
                    
                };
  
            }else
            {<!-- -->
                alert('No picture');
            }
        }

        var button=document.getElementById('btn-submit');
        var upfiles=document.getElementById("f1");
        var upbutton=document.getElementById("complate");
        //Show the preview after selecting the uploaded image
        upfiles.onchange=function(){<!-- -->
            previewUpdate(upfiles.files);
 
        }
        //Click the preview button to display and hide the preview image
        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";
            }
        };
        //Upload button submits the uploaded image
        upbutton.onclick=function(){<!-- -->
            complateUpdate();
            //Clear the array to prevent repeated submissions
            fL=[];
            var preview=document.getElementById("preview");
            //Clear the uploaded images in the preview area
            preview.innerHTML='';
          
        };

        
    </script>
    </body>
</html>

//The backend file is the ajax.php in xhr.open(“post”,”ajax.php”,true);

<?php
header('Content-type:text/plain;enctype:multipart/form-data');
if($files=$_FILES)
{<!-- -->
    //Set path
    $path="images/";
    if(!file_exists($path))
    {<!-- -->
        mkdir("$path",0700);
    }
    //Loop out multiple pictures
   for($i=0;$i<count($files);$i + + )
   {<!-- -->
   \t\t
   //Get file name suffix
        $pos[$i]=trim(strrchr($files[$i]['name'],"."),".");
        //Get file type
        $type[$i]=$files[$i]['type'];
        //Get the temporary name of the file
        $tmp_name[$i]=$files[$i]['tmp_name'];
        //Create a new image file with a complete random name
        $newfile[$i]=$path.strval(rand()).".$pos[$i]";
        //Use getimagesize() to get the type of each image, which must be the type of a temporary file. If you use $files[$i]['name'] to get the type, an error will occur.
        //getimagesize() says there is a vulnerability problem, it is best to use @ to hide the error display.
        //Why do we need to get the image type here? Because the type of image obtained by $files[$i]['type'] is not accurate
        $typemime[$i]=@getimagesize($files[$i]['tmp_name']);
        
        //array_diff compares the difference between two array values, which is to compare the value of parameter 1 to see if it is present in parameter 2. If one item is not present, this value will be output. This function can also compare objects.
        $result=array_diff($pos,array('png','jpeg','jpg','gif'));
        $rtype=array_diff($type,array('image/jpeg','image/png','image/jpg','image/gif'));
        
        if(count($result)===0 & amp; & amp; count($rtype)===0)
        {<!-- -->
        //Is the picture smaller than 1M?
            if($files[$i]['size']<1024*1000){<!-- -->
            //Move the temporary file to the newly created image
                if(move_uploaded_file($tmp_name[$i],$newfile[$i]))
                {<!-- -->
                    //Here we use the type ['mime'] obtained by getimagesize() to select which piece to use to create a new image.
                    //Use imagecreatefromjpreg/png/gif to effectively remove the malicious code in the picture, and also determine whether it is a picture.
                    //If it is not a picture, you cannot create a new picture. Currently, this is the most effective method to prevent malicious code. Other methods: such as writing code to clean up pictures, there will always be loopholes.
                    switch($typemime[$i]['mime'])
                    {<!-- -->
                        case 'image/jpeg':
                            $im=imagecreatefromjpeg($newfile[$i]);
                            break;
                        case 'image/png':
                            $im=imagecreatefrompng($newfile[$i]);
                            break;
                        case 'image/gif':
                            $im=imagecreatefromgif($newfile[$i]);
                            break;
                        case 'image/jpg':
                            $im=imagecreatefromjpeg($newfile[$i]);
                            break;
                        default:
                            $im=false;
                            break;
                    }
                    
                    if($im==false)
                    {<!-- -->
                        echo "Only support png, jpeg, gif, jpg image formats, please do not upload other types of files";
                        @unlink($newfile[$i]);
                        
                    }
                    else
                    {<!-- -->
                        //Create a new blank image again
                        $img_path[$i]=$path.date('YmdHis').strval(rand()).".$pos[$i]";
                        //Write the $im image object handle created above into a new blank image
                        imagejpeg($im,$img_path[$i]);
                        @unlink($newfile[$i]);
                        //Clean handle to release memory
                        imagedestroy($im);
                        echo $files[$i]['name'].'Upload successful';
                    }
                }else
                {<!-- -->
                    echo 'Upload error, make sure the image format is correct';
                }
            }else
            {<!-- -->
                echo 'The picture is too large and must be less than 1M';
            }
            
           
        }else
        {<!-- -->
            echo 'Upload failed! Incorrect file type, please ensure correct image format. ';
        }
        
   }
}else
{<!-- -->
    echo 'No data obtained';
}

?>