php發送請求上傳文件(原始socket方式)

php curl工具能很方便的發送請求。

php使用socket方式也可以發送請求,雖然原始,但是能夠體會到GET,POST,等請求的細節,對於理解HTTP協議有幫助。

<?php
/**
 * Created by PhpStorm.
 * User: zhaozhiliang
 * Date: 2018/6/25
 * Time: 下午4:59
 */

class HttpRequest
{
    private $_ip = '';
    private $_host = '';
    private $_url = '';
    private $_port = '';
    private $_errno = '';
    private $_errstr = '';
    private $_timeout = 15;
    private $_fp = null;

    private $_formdata = array();
    private $_filedata = array();

    //設置連接參數
    public function setConfig($config){
        $this->_ip = isset($config['ip'])? $config['ip'] : '';
        $this->_host = isset($config['host'])? $config['host'] : '';
        $this->_url = isset($config['url']) ? $config['url'] : '';
        $this->_port = isset($config['port']) ? $config['port'] : '';
        $this->_errno = isset($config['errno']) ? $config['errno'] : '';
        $this->_errstr = isset($config['errstr']) ? $config['errstr'] : '';
        $this->_timeout = isset($config['timeout']) ? $config['timeout'] : 15;

        //如果沒有ip,則用host代替
        if($this->_ip==''){
            $this->_ip = $this->_host;
        }
    }

    //設置表單數據
    public function setFormData($formdata = array()){
        $this->_formdata = $formdata;
    }

    //設置文件數據
    public function setFileData($filedata = array()){
        $this->_filedata = $filedata;
    }

    public function send($type= 'get'){
        $type = strtolower($type);

        if(!in_array($type, array('get','post','multipart'))){
            return false;
        }

        if(! $this->connect()){
            return false;
        }

        switch ($type){
            case 'get' :
                $out = $this->sendGet();
                break;
            case 'post' :
                $out = $this->sendPost();
                break;
            case 'multipart' :
                $out = $this->sendMultipart();
                break;
        }

        if(!$out){
            return false;
        }

        //發送數據
        fputs($this->_fp, $out);

        //讀取返回數據
        $response = '';
        while($row = fread($this->_fp, 4096)){
            $response .= $row;
        }

        //echo 'response:', $response;
        //斷開連接
        $this->disconnect();
        $pos = strpos($response, "\r\n\r\n");
        $response  = substr($response, $pos+ 4);
        return $response;

    }

    //創建連接
    private function connect(){
        $this->_fp = fsockopen($this->_ip, $this->_port, $this->_errno,$this->_errstr,$this->_timeout);
        if(!$this->_fp){
            return false;
        }
        return true;
    }

    //斷開連接
    private function disconnect(){
        if($this->_fp != null){
           fclose($this->_fp);
           $this->_fp = null;
        }
    }


    //GET 方式,
    private function sendGet(){
        //檢查是否空數據
        if(!$this->_formdata){
            return false;
        }

       //處理url
        $url = $this->_url.'?'.http_build_query($this->_formdata);

        $out = "GET ".$url." HTTP/1.1\r\n";
        $out .= "host: ".$this->_host."\r\n";
        $out .= "connection: close\r\n\r\n";

        return $out;
    }

    //POST 方式,處理髮送的數據
    private function sendPost(){
        //檢查是否空數據
        if(!$this->_formdata && !$this->_filedata){
            return false;
        }

        //form data
        $data = $this->_formdata ? $this->_formdata : array();

//        //file data
//        if($this->_filedata){
//            foreach($this->_filedata as $file){
//                if(file_exists($file['path'])){
//                    $data[$file['name']] = file_get_contents($file['path']);
//                }
//            }
//        }

        if(!$data){
            return false;
        }

        $data = http_build_query($data);

        $out = "POST ".$this->_url." HTTP/1.1\r\n";
        $out .= "host: ".$this->_host."\r\n";
        $out .= "content-type: application/x-www-form-urlencoded\r\n";
        $out .= "content-length: ".strlen($data)."\r\n";
        $out .= "connection: close\r\n\r\n";
        $out .= $data;

        return $out;
    }

    //multipart 方式, 發送數據文件使用此方式
    private function sendMultipart(){
        //檢查是否空數據
        if(!$this->_formdata && !$this->_filedata){
            return false;
        }

        //設置分割標識符
        $boundary = '---------------------------'.substr(md5(rand(0,32000)), 0, 10);
        $data = '--'.$boundary."\r\n";

        //form data
        $formdata = '';
        foreach($this->_formdata as $key=> $val){
            $formdata .= "content-disposition: form-data; name=\"".$key."\"\r\n";
            $formdata .= "content-type: text/plain\r\n\r\n";

            if(is_array($val)){
                $formdata .= json_encode($val)."\r\n";
            }else{
                $formdata .= rawurldecode($val)."\r\n";
            }
            $formdata .= '--'.$boundary."\r\n";
        }

        //file data
        $filedata = '';
        foreach($this->_filedata as $val){
            if(file_exists($val['path'])){
                $finfo    = finfo_open(FILEINFO_MIME_TYPE);
                $mimetype = finfo_file($finfo, $val['path']);
                finfo_close($finfo);

                $filedata .= "content-disposition: form-data; name=\"".$val['name']."\"; filename=\"".$val['filename']."\"\r\n";
                $filedata .= "content-type: ".$mimetype."\r\n\r\n";
                $filedata .= implode('', file($val['path']))."\r\n";
                $filedata .= "--".$boundary."\r\n";
            }
        }

        if(!$formdata && !$filedata){
            return false;
        }

        $data .= $formdata.$filedata."--\r\n\r\n";

        $out = "POST ".$this->_url." HTTP/1.1\r\n";
        $out .= "host: ".$this->_host."\r\n";
        $out .= "content-type: multipart/form-data; boundary=".$boundary."\r\n";
        $out .= "content-length: ".strlen($data)."\r\n";
        $out .= "connection: close\r\n\r\n";
        $out .= $data;

        return $out;

    }

}

/**
 * 以下爲測試
 */
$config = array(
    'ip' => 'blog.liang.com',
    'host' => 'blog.liang.com',
    'port' => 80,
    'errno' => '',
    'errstr' => '',
    'timeout' => 30,
    'url' => '/test_multipart.php'
);

$formdata = array(
    'name'=>'zhangsan',
    'real_name' => '張三',
    'age' => 29 ,
    'sex'=> 1,
    'address'=> 'beijing'
);

$filedata = array(
    array(
        'name' => 'logo',
        'filename' => 'logo.png',
        'path' => './logo.png'
    )
);

$obj = new HttpRequest();
$obj-> setConfig($config);
$obj-> setFormdata($formdata);
$obj-> setFileData($filedata);
#$result = $obj->send('get');
$result = $obj->send('post');
#$result = $obj->send('multipart');

print_r($result);


說明:

1. fileinfo 擴展需要phpize 安裝,不用重新下載包了,php5.5.7安裝包 的 ext目錄下有。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章