php curl文件上传

时间:2022-10-16 20:58:48
<?php
/**
 * 这是一个自动化部署的类, 非常简单,思想就是压缩,上传,然后解压覆盖,所以请小心使用.
 * @author liuchao <249757247@qq.com>
 * @date 2019-07-10
 */
/**
 * 配置
 */
$SECRET_KEY = 'whatthefuck';
$config = array(
    'upload_url' => 'http://tmp.szydweixin.com/deploy_110.php?key=' . $SECRET_KEY,
    'folders' => array(
            #'../application/controllers/',
            #'../application/libraries/',
            #'../application/models/'
//             '../application/config/api.php',
//             '../application/services/wx_user_service.php',
//             '../application/config/constants.php',
//             '../application/controllers/scene_code.php',
//             '../application/libraries/Strategy/BOSS/SZ/Balance_Strategy.php',
            '../t.php',
//             '../application/libraries/AES.php',
//             '../application/libraries/Scenes_code.php'
//             '../application/controllers/h5/auto_login.php',
//             '../application/controllers/schedule/contact_marketing_worker.php',
//             '../application/libraries/Strategy/Event/Subscribe_Strategy.php',
//             '../application/libraries/Strategy/Event/Scan_Strategy.php',
//             '../application/views/scene_code/add.php',
//             '../application/views/scene_code/index.php',
//             '../application/views/scene_code/scan_record.php',
//             '../application/views/second_marketing/edit_act.php',
//             '../application/views/wx_bind_setting/change_data.php',
//             '../application/views/wx_bind_setting/change_detail.php',
//             '../application/views/wx_bind_setting/reset_data.php',
//             '../application/views/h5/mobi/bind2.php',
//             '../static/js/h5_mobi/bind.js',
    ),
);
// 开始干活
if ($_FILES) {
    if (!isset($_GET['key']) || $_GET['key'] != $SECRET_KEY) {
        die('invalid request.');
    }
    $deploy = new DeployServer();
    $deploy->deploy($_FILES);
} else if (isset($_SERVER["argv"][1]) && $_SERVER["argv"][1] == 'start'){
    $deploy = new DeployClient($config);
    $deploy->deploy();
} else {
    die('you know. I am here...');
}
/**
 * 部署客户端类
 */
class DeployClient {
    private $config;
    
    public function __construct($config) {
        $this->config = $config;
    }
    public function deploy() {
        $tmp_dir = __DIR__ . '/' . md5(time()) . '.zip';
        // 生成压缩文件
        $zip = new ZipHelper();
        $zip->zip($this->config['folders'], $tmp_dir);
        echo $this->_post($this->config['upload_url'], $tmp_dir);
        unlink($tmp_dir);
    }
    private function _post($url, $file) {
        $file = array("file" => "@" . $file); //文件路径,前面要加@,表明是文件上传.
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); //php5.6默认是true,即禁用了使用@文件上传。php7.0废弃了CURLOPT_SAFE_UPLOAD,建议用curl_file_create函数或CURLFile
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $file);
        return curl_exec($curl);
    }
}
/**
 * 部署服务器类
 */
class DeployServer {
    public function deploy($files) {
        // step 1: 保存文件
        $tmp_dir = "tools/" . $_FILES["file"]["name"];
        move_uploaded_file($files["file"]["tmp_name"], $tmp_dir);
        // step 2: 解压并覆盖文件
        $zip = new ZipHelper();
        $zip->unzip($tmp_dir, __DIR__ . '/');
        // step 3: 删除临时文件
        unlink($tmp_dir);
        return true;
    }
}
/**
 * 压缩文件,解压文件类
 */
class ZipHelper {
    private $_zip;
    public function __construct() {
        $this->_zip = new ZipArchive();
    }
    function unzip($unzip, $dst) {
        $res = $this->_zip->open($unzip);
        if ($res === true) {
            if (!$this->_zip->extractTo($dst)) {
                echo 'extract fail to ' . $dst;
            }
            $this->_zip->close();
        } else {
            echo 'failed, code:' . $res;
        }
    }
    function zip($dirs, $dst) {
        $res = $this->_zip->open($dst, ZipArchive::CREATE);
        if ($res === true) {
            if (is_array($dirs)) {
                foreach ($dirs as $dir) {
                    $this->_zip($dir, $this->_zip);
                }
            } else {
                $this->_zip($dirs, $this->_zip);
            }
            $this->_zip->close();
        } else {
            echo 'failed';
        }
    }
    private function _zip($dir, &$zip) {
        if (!is_dir($dir)) {
            $zip->addFile($dir);
            return;
        }
        $dh = opendir($dir);
        while (($file = readdir($dh)) !== false) {
            if ($file == '.' || $file == '..') {
                continue;
            }
            if (filetype($dir . $file) == 'dir') {
                $this->_zip($dir . $file . '/', $zip);
            } else {
                $zip->addFile($dir . $file);
            }
        }
    }
}

用curl_file_create函数配合curl实现文件上传,增强代码的健壮性

<?php
if (!function_exists('curl_file_create')) {
     function curl_file_create($filename, $mimetype = '', $postname = '') {
         return "@$filename;filename="
             . ($postname ?: basename($filename))
             . ($mimetype ? ";type=$mimetype" : '');
     }
 }

$ch = curl_init();
$filename1 = 'E:/html/pim/php_weili_activities/uploads/activity_13_1547717462.jpg';
$filename2 = 'E:/html/pim/php_weili_activities/uploads/activity_13_1546510239_thumb.jpg';
$minetype1 = 'image/jpeg';
$minetype2 = 'image/jpeg';
$curl_file1 = curl_file_create($filename1,$minetype1,pathinfo($filename1,PATHINFO_BASENAME));
$curl_file2 = curl_file_create($filename2,$minetype2,pathinfo($filename2,PATHINFO_BASENAME));
$postData = [
    'file' => '111',
    'text' => '666',
    //'file'=>$curl_file1, //单个文件上传
    'file[0]'=>$curl_file1, //多个文件上传
    'file[1]'=>$curl_file1, //多个文件上传
];


curl_setopt($ch, CURLOPT_URL, 'http://localhost/phpinfo.php');
//curl结果不直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

//发送post  请求
curl_setopt($ch, CURLOPT_POST, 1);
// urlencoded 后的字符串,类似'para1=val1&para2=val2&...',也可以使用一个以字段名为键值,字段数据为值的数组 ,测试当值为数组时候  Content-Type头将会被设置成multipart/form-data 否则Content-Type 头会设置为 application/x-www-form-urlencoded 
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); //数组时候,以multipart/form-data提交 //curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); //application/x-www-form-urlencoded提交 //允许 cURL 函数执行的最长秒数
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
//不输出header 头信息
curl_setopt($ch, CURLOPT_HEADER,0);
//输出请求头
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE); //输出请求头,用curl_getinfo获取请求头
//不验证证书 信任任何证书
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// 检查证书中是否设置域名,0不验证 0:不检查通用名称(CN)属性
//1:检查通用名称属性是否存在
//2:检查通用名称是否存在,是否与服务器的主机名称匹配
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
//设置 在HTTP请求中包含一个"User-Agent: "头的字符串
//curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);


$res = curl_exec($ch);
$error_no = curl_errno($ch);
$info = curl_getinfo($ch);
$err_msg = '';
if ($error_no) {
    $err_msg = curl_error($ch);
} else {
    print_r($res);
    //var_dump($info); //CURLINFO_HEADER_OUT选项为true设置下,可获取请求头信息
}
curl_close($ch);

curl_getinfo信息

Array
(
    [url] => http://localhost/phpinfo.php
    [content_type] => text/html; charset=utf-8
    [http_code] => 200
    [header_size] => 237
    [request_size] => 191
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 1.547
    [namelookup_time] => 0.016
    [connect_time] => 0.016
    [pretransfer_time] => 0.437
    [size_upload] => 30066
    [size_download] => 837
    [speed_download] => 541
    [speed_upload] => 19435
    [download_content_length] => -1
    [upload_content_length] => 30066
    [starttransfer_time] => 0.453
    [redirect_time] => 0
    [redirect_url] => 
    [primary_ip] => ::1
    [certinfo] => Array
        (
        )

    [primary_port] => 80
    [local_ip] => ::1
    [local_port] => 63148
    [request_header] => POST /phpinfo.php HTTP/1.1
Host: localhost
Accept: */*
Content-Length: 30066
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------c7de087ef011a0f8


)

$_FILES, $_POST

Array
(
    [file] => 111
    [text] => 666
)


Array
(
    [file] => Array
        (
            [name] => Array
                (
                    [0] => activity_13_1547717462.jpg
                    [1] => activity_13_1547717462.jpg
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [0] => C:\Windows\phpD6C8.tmp
                    [1] => C:\Windows\phpD6D8.tmp
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 14753
                    [1] => 14753
                )

        )

)

说明:$content = file_get_contents("php://input") 不可以获取multipart/form-data的数据,可以获取application/x-www-form-urlencoded的数据