欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

文件上传和下载实例源码

程序员文章站 2022-12-08 21:33:44
效果图 首先是封装好的图片类(缩放及生成水印) GDBasic.php

效果图

文件上传和下载实例源码

文件上传和下载实例源码

首先是封装好的图片类(缩放及生成水印)

gdbasic.php

<?php
/**
 * gdbasic.php
 * description gd基础类
 */

namespace test\lib;


class gdbasic
{
    protected static $_check =false;

    //检查服务器环境中gd库
    public static function check()
    {
        //当静态变量不为false
        if(static::$_check)
        {
            return true;
        }

        //检查gd库是否加载
        if(!function_exists("gd_info"))
        {
            throw new \exception('gd is not exists');
        }

        //检查gd库版本
        $version = '';
        $info = gd_info();
        if(preg_match("/\\d+\\.\\d+(?:\\.\\d+)?/", $info["gd version"], $matches))
        {
            $version = $matches[0];
        }

        //当gd库版本小于2.0.1
        if(!version_compare($version,'2.0.1','>='))
        {
            throw new \exception("gd requires gd version '2.0.1' or greater, you have " . $version);
        }

        self::$_check = true;
        return self::$_check;
    }
}

image.php

 

<?php
/**
 * image.php
 * description 图像类
 */

namespace test\lib;

require_once 'gdbasic.php';

class image extends gdbasic
{
    protected $_width;
    protected $_height;
    protected $_im;
    protected $_type;
    protected $_mime;
    protected $_real_path;

    
    public function __construct($file)
    {
        //检查gd库
        self::check();
        $imageinfo = $this->createimagebyfile($file);
        $this->_width = $imageinfo['width'];
        $this->_height = $imageinfo['height'];
        $this->_im = $imageinfo['im'];
        $this->_type = $imageinfo['type'];
        $this->_real_path = $imageinfo['real_path'];
        $this->_mime = $imageinfo['mime'];
    }


    /**
     * 根据文件创建图像
     * @param $file
     * @return array
     * @throws \exception
     */
    public function createimagebyfile($file)
    {
        //检查文件是否存在
        if(!file_exists($file))
        {
            throw new \exception('file is not exits');
        }

        //获取图像信息
        $imageinfo = getimagesize($file);
        $realpath = realpath($file);
        if(!$imageinfo)
        {
            throw new \exception('file is not image file');
        }

        switch($imageinfo[2])
        {
            case imagetype_gif:
                $im = imagecreatefromgif($file);
                break;
            case imagetype_jpeg:
                $im = imagecreatefromjpeg($file);
                break;
            case imagetype_png:
                $im = imagecreatefrompng($file);
                break;
            default:
                throw  new \exception('image file must be png,jpeg,gif');
        }

        return array(
            'width'     => $imageinfo[0],
            'height'    => $imageinfo[1],
            'type'      => $imageinfo[2],
            'mime'      => $imageinfo['mime'],
            'im'        => $im,
            'real_path' => $realpath,
        );

    }

    /**
     * 缩略图
     * @param  int $width 缩略图高度
     * @param  int $height 缩略图宽度
     * @return $this
     * @throws \exception
     */
    public function resize($width, $height)
    {
        if(!is_numeric($width) || !is_numeric($height))
        {
            throw new \exception('image width or height must be number');
        }
        //根据传参的宽高获取最终图像的宽高
        $srcw = $this->_width; 
        $srch = $this->_height;

        if($width <= 0 || $height <= 0)
        {
            $desw = $srcw;//缩略图高度
            $desh = $srch;//缩略图宽度
        }
        else
        {
            $srcp = $srcw / $srch;//宽高比
            $desp = $width / $height; 

            if($width > $srcw)
            {
                if($height > $srch)
                {
                    $desw = $srcw;
                    $desh = $srch;
                }
                else
                {
                    $desh = $height;
                    $desw = round($desh * $srcp);
                }
            }
            else
            {
                if($desp > $srcp)
                {
                    $desw = $width;
                    $desh = round($desw / $srcp);
                }
                else
                {
                    $desh = $height;
                    $desw = round($desh * $srcp);
                }
            }
        }

        //php版本小于5.5
        if(version_compare(php_version, '5.5.0', '<'))
        {
            $desim = imagecreatetruecolor($desw, $desh);
            if(imagecopyresampled($desim, $this->_im, 0, 0, 0, 0, $desw, $desh, $srcw, $srch))
            {
                imagedestroy($this->_im);
                $this->_im = $desim;
                $this->_width = imagesx($this->_im);
                $this->_height = imagesy($this->_im);
            }
        }
        else
        {
            if($desim = imagescale($this->_im, $desw, $desh))
            {
                $this->_im = $desim;
                $this->_width = imagesx($this->_im);
                $this->_height = imagesy($this->_im);
            }

        }

        return $this;
    }


    /**
     * 根据百分比生成缩略图
     * @param int $percent 1-100
     * @return image
     * @throws \exception
     */
    public function resizebypercent($percent)
    {
        if(intval($percent) <= 0)
        {
            throw new \exception('percent must be gt 0');
        }

        $percent = intval($percent) > 100 ? 100 : intval($percent);

        $percent = $percent / 100;

        $desw = $this->_width * $percent;
        $desh = $this->_height * $percent;
        return $this->resize($desw, $desh);
    }


    /**
     * 图像旋转
     * @param $degree
     * @return $this
     */
    public function rotate($degree)
    {
        $degree = 360 - intval($degree);
        $back = imagecolorallocatealpha($this->_im,0,0,0,127);
        $im = imagerotate($this->_im,$degree,$back,1);
        imagesavealpha($im,true);
        imagedestroy($this->_im);
        $this->_im = $im;
        $this->_width = imagesx($this->_im);
        $this->_height = imagesy($this->_im);
        return $this;
    }


    /**
     * 生成水印
     * @param file $water 水印图片
     * @param int $pct   透明度
     * @return $this
     */
    public function watermask($water ='',$pct = 60 )
    {
        //根据水印图像文件生成图像资源
        $waterinfo = $this->createimagebyfile($water);
        imagecopymerge();
        //销毁$this->_im
        $this->_im = $waterinfo['im'];
        $this->_width = imagesx($this->_im);
        $this->_height = imagesy($this->_im);
        return $this;

    }



    /**
     * 图片输出
     * @return bool
     */
    public function show()
    {
        header('content-type:' . $this->_mime);
        if($this->_type == 1)
        {
            imagegif($this->_im);
            return true;
        }

        if($this->_type == 2)
        {
            imagejpeg($this->_im, null, 80);
            return true;
        }

        if($this->_type == 3)
        {
            imagepng($this->_im);
            return true;
        }
    }

    /**
     * 保存图像文件
     * @param $file
     * @param null $quality
     * @return bool
     * @throws \exception
     */
    public function save($file, $quality = null)
    {
        //获取保存目的文件的扩展名
        $ext = pathinfo($file, pathinfo_extension);
        $ext = strtolower($ext);
        if(!$ext || !in_array($ext, array('jpg', 'jpeg', 'gif', 'png')))
        {
            throw new \exception('image save file must be jpg ,png,gif');
        }

        if($ext === 'gif')
        {
            imagegif($this->_im, $file);
            return true;
        }
        if($ext === 'jpeg' || $ext === 'jpg')
        {
            if($quality > 0)
            {
                if($quality < 1)
                {
                    $quality = 1;
                }
                if($quality > 100)
                {
                    $quality = 100;
                }

                imagejpeg($this->_im, $file, $quality);
            }
            else
            {
                imagejpeg($this->_im, $file);
            }
            return true;
        }

        if($ext === 'png')
        {
            imagepng($this->_im, $file);
            return true;
        }

    }
}

style样式不是重点,先不放了

然后是ajax类封装的文件 ajax.js

let $ = new class {

    constructor()
    {
        this.xhr = new xmlhttprequest();
        this.xhr.onreadystatechange = () => {
            if (this.xhr.readystate == 4 && this.xhr.status == 200) {
                // process response text
                let response = this.xhr.responsetext;
                if (this.type == "json") {
                    response = json.parse(response);
                }
                this.callback(response);
            }
        }
    }

    get(url, parameters, callback, type = "text")
    {
        // url = test.php?username=zhangsan&age=20
        // parameters = {"username": "zhangsan", "age": 20}
        let data = this.parseparameters(parameters);
        if (data.length > 0) {
            url += "?" + data;
        }
        this.type = type;
        this.callback = callback;
        this.xhr.open("get", url, true);
        this.xhr.send();
    }

    post(url, parameters, callback, type = "text")
    {
        let data = this.parseparameters(parameters);
        this.type = type;
        this.callback = callback;
        this.xhr.open("post", url, true);
        this.xhr.setrequestheader("content-type", "application/x-www-form-urlencoded");
        this.xhr.send(data);
    }

    parseparameters(parameters)
    {
        // username=zhangsan&age=20
        let buildstr = "";
        for (let key in parameters) {
            let str = key + "=" + parameters[key];
            buildstr += str + "&";
        }
        return buildstr.substring(0, buildstr.length - 1);
    }
};

首页文件index.php

<!doctype html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>文件上传和下载</title>
    <!-- bootstrap -->
    <link href="style/css/bootstrap.min.css" rel="stylesheet">
    <link href="style/css/site.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <style>
        .projects .thumbnail .caption {
            height: auto;
            max-width: auto;
        }
        .image{
            margin:10px auto;
            border-radius:5px;
            overflow:hidden;
            border:1px solid #ccc;
        }
        .image .caption p{
            text-align: center;
        }
    </style>
</head>

<body>
    <!--导航栏-->
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".navbar-collapse">
                  <span class="sr-only">toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand hidden-sm" href="" onclick="_hmt.push(['_trackevent', 'navbar', 'click', 'navbar-首页'])">xx网</a>
            </div>
            <div class="navbar-collapse collapse" role="navigation">
                <ul class="nav navbar-nav">
                    <li class="hidden-sm hidden-md">
                        <a href="" target="_blank"></a>
                    </li>
                    <li>
                        <a href="" target="_blank"></a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <!--导航栏结束-->
    <!--巨幕-->
    <div class="jumbotron masthead">
        <div class="container">
            <h1>文件上传下载</h1>
            <h2>实现文件的上传和下载功能</h2>
            <p class="masthead-button-links">
                <form class="form-inline" onsubmit="return false;">
                    <div class="form-group">
                        <input type="search" class="form-control keywords" id="exampleinputname2" placeholder="输入搜索内容" name="keywords" value="">
                        <button class="btn btn-default searchbtn" type="submit">搜索</button>
                        <button type="button" class="btn btn-primary btn-default" data-toggle="modal" data-target="#mymodal">  上传  </button>
                    </div>
                </form>
            </p>
        </div>
    </div>
    <!--巨幕结束-->
    <!-- 模态框 -->
    <div class="modal fade" id="mymodal" tabindex="-1" role="dialog" aria-labelledby="mymodallabel">
        <div class="modal-dialog" role="document">
            <form class="form-inline" action="upload_class.php" method="post" enctype="multipart/form-data">
                <input type="hidden" name="max_file_size" value="10240000" />
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="close"><span aria-hidden="true">&times;</span></button>
                        <h4 class="modal-title" id="mymodallabel">上传图片</h4>
                    </div>
                    <div class="modal-body">
                        <p>选择图片:</p><input type="file" id="image" name="test_pic[]">
                        <br/>
                        <p>图片描述:</p><textarea class="form-control" cols="75" name="description" id="info"></textarea>
                        <br/><br/>
                        <p>
                          是否添加水印:
                          <select name="mark">
                            <option value="1">添加</option>
                            <option value="0">不添加</option>
                          </select>
                        </p>
                        <br/>
                        <p>
                          图片宽度比例:
                            <select name="scale">
                              <option value="800*600">800*600</option>
                              <option value="600*450">600*450</option>
                              <option value="400*300">400*300</option>
                            </select>
                        </p>
                    </div>
                    <div class="modal-footer">
                        <button type="submit" class="btn btn-default" name="submit" id="submit" onclick="show(this)">上传</button>
                        <button type="reset" class="btn btn-primary">重置</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <!--模态框结束-->

    <div class="container projects">
        <div class="projects-header page-header">
            <h2>上传图片展示</h2>
            <p>将上传的图片展示在页面中</p>
        </div>
        <div class="row pic_body">
            <!-- 使用js显示图片 -->
        </div>
        <!--分页-->
        <nav aria-label="page navigation" style="text-align:center">
            <ul class="pagination pagination-lg">
                <!-- 使用js显示页码 -->
            </ul>
        </nav>
    </div>

    <footer class="footer  container">
        <div class="row footer-bottom">
            <ul class="list-inline text-center">
                <h4><a href="class.test.com" target="_blank">class.test.com</a> | xx网</h4>
            </ul>
        </div>
    </footer>

    <!-- jquery (necessary for bootstrap's javascript plugins) -->
    <script src="style/js/jquery.min.js"></script>
    <!-- include all compiled plugins (below), or include individual files as needed -->
    <script src="style/js/bootstrap.min.js"></script>
    <script type="text/javascript">
        function show(){
          if(document.getelementbyid("image").value == ''){
            alert('请选择图片');
          }
          if(document.getelementbyid("info").value == ''){
            alert('请输入图片描述');
          }
        }
    </script>
    <!-- jquery first, then popper.js, then bootstrap js -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-kj3o2dktikvyik3uenzmm7kckrr/re9/qpg6aazgjwfdmvna/gpgff93hxpg5kkn" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-apnbgh9b+y1qktv3rn7w3mgpxhu9k/scqsap7huibx39j7fakfpskvxusvfa0b4q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-jzr6spejh4u02d8jot6vlehfe/jqgirrsqqxsffwpi1mquvdayjuar5+76pvcmyl" crossorigin="anonymous"></script>
    <script src="style/js/ajax.js"></script>
    <script>
        let pageno = 1;
        let kws = '';
        let searchbtn = document.getelementsbyclassname('searchbtn')[0];
        searchbtn.onclick = function() {
            let search = document.getelementsbyclassname('keywords')[0];
            let keywords = search.value;
            requestdata(pageno, keywords);
            kws = keywords;
        };

        let requestpage = function(page) {
            requestdata(page, kws);
            pageno = page;
        };


        let requestdata = function(page_number, keywords) {
            let pagination = document.getelementsbyclassname('pagination')[0];
            let pic_body = document.getelementsbyclassname('pic_body')[0];
            pic_body.innerhtml = '<p style="text-align:center"><i class="fa fa-spinner fa-spin" style="font-size:24px"></i> 加载中...</p>';
            $.get('search.php', {"page": page_number, "keywords": keywords}, function (res) {
                let divs = '';
                if (res.code == 1) {
                    // 请求成功
                    res.rows.foreach(function (item) {
                        let div = '<div class="col-sm-6 col-md-3 col-lg-4"><div class="image"><a href="' + item.path + '" target="_blank"><img class="img-responsive" src="' + item.path + '" ></a><div class="caption"><p>' + item.info + '</p></div></div></div>';
                        divs += div;
                    });
                    pic_body.innerhtml = divs;


                    // 加载页码导航
                    // previous
                    let previousbtn = '';
                    if (res.page_number == 1) {
                        previousbtn = '<li class="page-item disabled"><a class="page-link" href="javascript:requestpage(' + (res.page_number - 1) + ');">previous</a></li>';
                    } else {
                        previousbtn = '<li class="page-item"><a class="page-link" href="javascript:requestpage(' + (res.page_number - 1) + ');">previous</a></li>';
                    }
                    // next
                    let nextbtn = '';
                    if (res.page_total == res.page_number) {
                        nextbtn = '<li class="page-item disabled"><a class="page-link" href="javascript:requestpage(' + (res.page_number + 1) + ');">next</a></li>';
                    } else {
                        nextbtn = '<li class="page-item"><a class="page-link" href="javascript:requestpage(' + (res.page_number + 1) + ');">next</a></li>'
                    }

                    let pages = previousbtn;
                    for (let page = 1; page <= res.page_total; page++) {
                        let active = '';
                        if (page == res.page_number) {
                            active = 'active';
                        }
                        pages += '<li class="page-item ' + active + '"><a class="page-link" href="javascript:requestpage(' + page + ');">' + page + '</a></li>';
                    }
                    pages += nextbtn;
                    pagination.innerhtml = pages;
                }   
            },'json');
        };
        requestdata(1, '');
    </script>
</body>
</html>

图片相关功能处理 upload_class.php

<?php

//接收传过来的数据
$description=$_post['description'];//描述
$mark=$_post['mark'];//水印
$scale=$_post['scale'];//比例 800*600
$path='';//图片存储路径


//根据比例获取宽高
$width=substr($scale,0,3);//800
$height=substr($scale,4,3);//600


//上传图片并存储
require('uploadfile.php');

$upload = new uploadfile('test_pic');
$upload->setdestinationdir('./uploads');
$upload->setallowmime(['image/jpeg', 'image/gif','image/png']);
$upload->setallowext(['gif', 'jpeg','jpg','png']);
$upload->setallowsize(2*1024*1024);
if ($upload->upload()) {
    $filename=$upload->getfilename()[0];
    $dir=$upload->getdestinationdir();
    $path=$dir.'/'.$filename;//图片存储的实际路径
    
} else {
    var_dump($upload->geterrors());
}


//根据比例调整图像
require_once './lib/image.php';
$image = new \test\lib\image($path);
//放大并保存
$image->resize($width,$height)->save($path);

$info = getimagesize($path);
//根据不同的图像type 来创建图像
switch($info[2])
{
    case 1://imagetype_gif
        $image = imagecreatefromgif($path);
        break;
    case imagetype_jpeg:
        $image = imagecreatefromjpeg($path);
        break;
    case 3:
        $image = imagecreatefrompng($path);
        break;

    default:
        echo '图像格式不支持';
        break;

}
    
//添加水印
if($mark==1){

    $logo=imagecreatefrompng('./uploads/logo.png');
    //添加水印
    imagecopy($image,$logo,0,0,0,0,imagesx($logo),imagesy($logo));
    //header('content-type:image/png');
    imagejpeg($image,$path);
}

$dst_image=imagecreatetruecolor($width,$height);
//拷贝源图像左上角起始
imagecopy( $dst_image, $image, 0, 0, 0, 0, $width, $height );
imagejpeg($dst_image,$path);

//存入数据库
$servername = "localhost";
$username = "root";
$password = "123456";
$dbname = "pic";

try {
$conn = new pdo("mysql:host=$servername;dbname=$dbname", $username, $password);
// 设置 pdo 错误模式,用于抛出异常
$conn->setattribute(pdo::attr_errmode, pdo::errmode_exception);
$sql = "insert into pic(`path`, `mark`, `scale`,`info`)
values ('$path', '$mark', '$scale','$description')";
// 使用 exec() ,没有结果返回
$conn->exec($sql);
    exit("<script>alert(\"图片上传成功!\");window.location=\"index.php\";</script>");
}
catch(pdoexception $e)
{
    echo $sql . "<br>" . $e->getmessage();
}

封装好的文件上传类 uploadfile.php

<?php
/**
 * created by phpstorm.
 * user: jasonlee
 * date: 2018/11/11
 * time: 22:01
 */

class uploadfile
{

    /**
     *
     */
    const upload_error = [
        upload_err_ini_size => '文件大小超出了php.ini当中的upload_max_filesize的值',
        upload_err_form_size => '文件大小超出了max_file_size的值',
        upload_err_partial => '文件只有部分被上传',
        upload_err_no_file => '没有文件被上传',
        upload_err_no_tmp_dir => '找不到临时目录',
        upload_err_cant_write => '写入磁盘失败',
        upload_err_extension => '文件上传被扩展阻止',
    ];

    /**
     * @var
     */
    protected $field_name;

    /**
     * @var string
     */
    protected $destination_dir;

    /**
     * @var array
     */
    protected $allow_mime;

    /**
     * @var array
     */
    protected $allow_ext;

    /**
     * @var
     */
    protected $file_org_name;

    /**
     * @var
     */
    protected $file_type;

    /**
     * @var
     */
    protected $file_tmp_name;

    /**
     * @var
     */
    protected $file_error;

    /**
     * @var
     */
    protected $file_size;

    /**
     * @var array
     */
    protected $errors;

    /**
     * @var
     */
    protected $extension;

    /**
     * @var
     */
    protected $file_new_name;

    /**
     * @var float|int
     */
    protected $allow_size;

    /**
     * uploadfile constructor.
     * @param $keyname
     * @param string $destinationdir
     * @param array $allowmime
     * @param array $allowext
     * @param float|int $allowsize
     */
    public function __construct($keyname, $destinationdir = './uploads', $allowmime = ['image/jpeg', 'image/gif'], $allowext = ['gif', 'jpeg'], $allowsize = 2*1024*1024)
    {
        $this->field_name = $keyname;
        $this->destination_dir = $destinationdir;
        $this->allow_mime = $allowmime;
        $this->allow_ext = $allowext;
        $this->allow_size = $allowsize;
    }

    /**
     * @param $destinationdir
     */
    public function setdestinationdir($destinationdir)
    {
        $this->destination_dir = $destinationdir;
    }

    /**
     * @param $allowmime
     */
    public function setallowmime($allowmime)
    {
        $this->allow_mime = $allowmime;
    }

    /**
     * @param $allowext
     */
    public function setallowext($allowext)
    {
        $this->allow_ext = $allowext;
    }

    /**
     * @param $allowsize
     */
    public function setallowsize($allowsize)
    {
        $this->allow_size = $allowsize;
    }

    /**
     * @return bool
     */
    public function upload()
    {
        // 判断是否为多文件上传
        $files = [];
        if (is_array($_files[$this->field_name]['name'])) {
            foreach($_files[$this->field_name]['name'] as $k => $v) {
                $files[$k]['name'] = $v;
                $files[$k]['type'] = $_files[$this->field_name]['type'][$k];
                $files[$k]['tmp_name'] = $_files[$this->field_name]['tmp_name'][$k];
                $files[$k]['error'] = $_files[$this->field_name]['error'][$k];
                $files[$k]['size'] = $_files[$this->field_name]['size'][$k];
            }
        } else {
            $files[] = $_files[$this->field_name];
        }

        foreach($files as $key => $file) {
            // 接收$_files参数
            $this->setfileinfo($key, $file);

            // 检查错误
            $this->checkerror($key);

            // 检查mime类型
            $this->checkmime($key);

            // 检查扩展名
            $this->checkext($key);

            // 检查文件大小
            $this->checksize($key);

            // 生成新的文件名称
            $this->generatenewname($key);

            if (count((array)$this->geterror($key)) > 0) {
                continue;
            }
            // 移动文件
            $this->movefile($key);
        }
        if (count((array)$this->errors) > 0) {
            return false;
        }
        return true;
    }

    /**
     * @return array
     */
    public function geterrors()
    {
        return $this->errors;
    }

    /**
     * @param $key
     * @return mixed
     */
    protected function geterror($key)
    {
        return $this->errors[$key];
    }

    /**
     *
     */
    protected function setfileinfo($key, $file)
    {
        // $_files  name type temp_name error size
        $this->file_org_name[$key] = $file['name'];
        $this->file_type[$key] = $file['type'];
        $this->file_tmp_name[$key] = $file['tmp_name'];
        $this->file_error[$key] = $file['error'];
        $this->file_size[$key] = $file['size'];
    }


    /**
     * @param $key
     * @param $error
     */
    protected function seterror($key, $error)
    {
        $this->errors[$key][] = $error;
    }


    /**
     * @param $key
     * @return bool
     */
    protected function checkerror($key)
    {
        if ($this->file_error > upload_err_ok) {
            switch($this->file_error) {
                case upload_err_ini_size:
                case upload_err_form_size:
                case upload_err_partial:
                case upload_err_no_file:
                case upload_err_no_tmp_dir:
                case upload_err_cant_write:
                case upload_err_extension:
                    $this->seterror($key, self::upload_error[$this->file_error]);
                    return false;
            }
        }
        return true;
    }


    /**
     * @param $key
     * @return bool
     */
    protected function checkmime($key)
    {
        if (!in_array($this->file_type[$key], $this->allow_mime)) {
            $this->seterror($key, '文件类型' . $this->file_type[$key] . '不被允许!');
            return false;
        }
        return true;
    }


    /**
     * @param $key
     * @return bool
     */
    protected function checkext($key)
    {
        $this->extension[$key] = pathinfo($this->file_org_name[$key], pathinfo_extension);
        if (!in_array($this->extension[$key], $this->allow_ext)) {
            $this->seterror($key, '文件扩展名' . $this->extension[$key] . '不被允许!');
            return false;
        }
        return true;
    }

    /**
     * @return bool
     */
    protected function checksize($key)
    {
        if ($this->file_size[$key] > $this->allow_size) {
            $this->seterror($key, '文件大小' . $this->file_size[$key] . '超出了限定大小' . $this->allow_size);
            return false;
        }
        return true;
    }


    /**
     * @param $key
     */
    protected function generatenewname($key)
    {
        $this->file_new_name[$key] = uniqid() . '.' . $this->extension[$key];
    }


    /**
     * @param $key
     * @return bool
     */
    protected function movefile($key)
    {
        if (!file_exists($this->destination_dir)) {
            mkdir($this->destination_dir, 0777, true);
        }
        $newname = rtrim($this->destination_dir, '/') . '/' . $this->file_new_name[$key];
        if (is_uploaded_file($this->file_tmp_name[$key]) && move_uploaded_file($this->file_tmp_name[$key], $newname)) {
            return true;
        }
        $this->seterror($key, '上传失败!');
        return false;
    }

    /**
     * @return mixed
     */
    public function getfilename()
    {
        return $this->file_new_name;
    }

    /**
     * @return string
     */
    public function getdestinationdir()
    {
        return $this->destination_dir;
    }

    /**
     * @return mixed
     */
    public function getextension()
    {
        return $this->extension;
    }

    /**
     * @return mixed
     */
    public function getfilesize()
    {
        return $this->file_size;
    }

}

搜索功能实现 search.php

<?php

// 接收请求数据
$pageno = $_get['page'] ?? 1;
$pagesize = 9;

// 接收查询参数
$keywords = $_get['keywords'] ?? '';

$data = [];
//模拟加载中的图标sleep(3);
try {
    $pdo = new pdo('mysql:host=localhost:3306;dbname=pic',
        'root',
        '123456',
        [pdo::attr_errmode => pdo::errmode_exception]
    );

    // 请求mysql 查询记录总数
    $sql = 'select count(*) as aggregate from pic';
    if (strlen($keywords) > 0) {
        $sql .= ' where info like ?';
    }
    $stmt = $pdo->prepare($sql);
    if (strlen($keywords) > 0) {
        $stmt->bindvalue(1, '%' . $keywords . '%', pdo::param_str);
    }
    $stmt->execute();
    $total = $stmt->fetch(pdo::fetch_assoc)['aggregate'];
    
    // 计算最大页码,设置页码边界
    $minpage = 1;
    $maxpage = ceil($total / $pagesize); // 3.6
    $pageno = max($pageno, $minpage);
    $pageno = min($pageno, $maxpage);
    $offset = ($pageno - 1) * $pagesize;


    $sql="select `path`,`info` from pic ";
    if (strlen($keywords) > 0) {
        $sql .= ' where info like ?';
    }
    $sql .= 'order by id desc limit ?, ?';
    $stmt = $pdo->prepare($sql);
    if (strlen($keywords) > 0) {
        $stmt->bindvalue(1, '%' . $keywords . '%', pdo::param_str);
        $stmt->bindvalue(2, (int)$offset, pdo::param_int);
        $stmt->bindvalue(3, (int)$pagesize, pdo::param_int);
    } else {
        $stmt->bindvalue(1, (int)$offset, pdo::param_int);
        $stmt->bindvalue(2, (int)$pagesize, pdo::param_int);
    }
    $stmt->execute();
    $results = $stmt->fetchall(pdo::fetch_assoc);
    $data = [
        'code' => 1,
        'msg' => 'ok',
        'rows' => $results,
        'total_records' => (int)$total,
        'page_number' => (int)$pageno,
        'page_size' => (int)$pagesize,
        'page_total' => (int)$maxpage,
    ];   

} catch (pdoexception $e) {
    $data = [
        'code' => 0,
        'msg' => $e->getmessage(),
        'rows' => [],
        'total_records' => 0,
        'page_number' => 0,
        'page_size' => (int)$pagesize,
        'page_total' => 0,
    ];
}

header('content-type: application/json');
echo json_encode($data);

最后数据库格式 

/*
navicat mysql data transfer

source server         : localhost
source server version : 80012
source host           : localhost:3306
source database       : pic

target server type    : mysql
target server version : 80012
file encoding         : 65001

date: 2020-01-14 16:22:49
*/

set foreign_key_checks=0;

-- ----------------------------
-- table structure for pic
-- ----------------------------
drop table if exists `pic`;
create table `pic` (
  `id` int(10) unsigned not null auto_increment,
  `path` varchar(255) default null,
  `mark` tinyint(3) default null,
  `scale` varchar(255) default null,
  `info` varchar(255) default null,
  primary key (`id`)
) engine=myisam auto_increment=3 default charset=utf8;

-- ----------------------------
-- records of pic
-- ----------------------------
insert into `pic` values ('1', './uploads/5e1d788084cc5.jpg', '1', '800*600', '这是测试图片1');
insert into `pic` values ('2', './uploads/5e1d789766591.jpg', '1', '600*450', '这是测试图片2');