Loading...
[PHP] 소켓통신으로 POST 데이터 와 파일전송 서포트 함수 | socket_post_request
REDINFO
약 2년전 2022-02-05 19:37:33

PHP에서 다른 서버로 파일을 전송하는 방법에는 크게 CURL 통신과 소켓통신이 있다. 

 

솔직히 회사에서 사용한다면 CURL 통신을 추천하지만 부득이하게 CURL 통신으로 안될경우

소켓통신을 사용하는것을 추천한다. 

 

소켓통신이 사용하는 방법이 까다롭고, 서버에 따라 잘 안되는 경우도 있는것같다. 

 

이번에 만든 함수같은 경우 전에 다른 서버에서 사용했던 함수였는데 이상하게도 

현재 서버에서는 500 에러가 계속 발생되어 삽질을 많이 하면서 수정을 했다. 

 

따라서 모든 서버에서 된다는 보장은 못하겠다. 

 

일단 소스코드는 아래와 같다. 

 

socket_post_request 함수
<?php 
/*
    ** 소켓 post 전송 
    $url : 전송 url 
    $_post => $_POST 
    $_files 
        => array(
            array(
                'key'=>'키값' ==> 필수
            )
        );
    $response => 응답을 받을 경우 true 
*/
if( function_exists('socket_post_request') === false){
    function socket_post_request($url, $_post = array(), $_files = array(), $response = false) {

        $parse_url = parse_url($url);
        if(empty($parse_url['host'])) { return false;}
   
        if( $parse_url['scheme'] == 'https'){ $parse_url['port'] = 443; }
        else{ $parse_url['port'] = 80; }

        $_post = array_filter($_post);
        $_files = array_filter($_files);
        if( count($_post) < 1 && count($_files) < 1 ){ return false; }

        $hostname = ($parse_url['scheme'] == 'https'?'ssl://':null).$parse_url['host'];
        $fp = fsockopen($hostname, $parse_url['port'],  $errno, $errstr, 30);

        if( (!empty($errno) && $errno != 0)  || (!empty($errstr))){ return false; }

        $out = "POST ".$parse_url['path']." HTTP/1.1\r\n";
        $out.= "Host: ".$parse_url['host']."\r\n";

        srand((double)microtime()*1000000);
        $boundary = substr(md5(rand(0,32000)),0,10);

        $data = '';
        // THIS IS POST DATA SET
        foreach($_post as $KEY=>$VAL){
            $data .="--".$boundary."\r\n";
            $data .= "Content-Disposition: form-data; name=\"".$KEY."\"\r\n";
            $data .= "\r\n".$VAL."\r\n";
        }
        
        foreach($_files as $k=>$v){
            $KEY = $v['key'];
            $file_type = $v['type'];
            $file_tmp_name = $v['tmp_name'];
            $file_name = $v['name'];            
            $content_file = implode("",file($file_tmp_name));
            $data .= "--".$boundary."\r\n";
            $data .= "Content-Disposition: form-data; name=\"".$KEY."\"; filename=\"".$file_name."\"\r\n";
            $data .= "Content-Type: ".$file_type."\r\n\r\n";
            $data .= ($content_file)."\r\n";
        }

        $data .= "--".$boundary;
        $data .="--\r\n";

        // 헤더 -- 헤더 그리고 바디에서 연결선은 newline이 2개
        $out .= "Content-Type: multipart/form-data; boundary=".$boundary."\r\n";
        $out .= "Content-Length: ".strlen($data)."\r\n";
        $out .= "Connection: Close\r\n\r\n"; // 커넥션

        $rst = '';
        if( $response === true) {
            fputs($fp,$out.$data); 
            ob_start();
            while(!feof($fp)) {echo fgets($fp, 4096);}
            $rst = ob_get_clean();
        }else{
            // $rst 가 0보다 크다면 거의 성공이라 보면 된다.
            $rst = fwrite($fp, $out.$data);
            // usleep(100000); // 지연발생 -> 특정 서버에서 파일전송이 잘 안될떄가 있을떄 지연을 발생시키는게 좋다.
        }

        fclose($fp);

        return $rst;
    }
}else{ echo "socket_post_request overlap"; }
?>

 

예제

<?php 
if(!empty($_POST) || !empty($_FILES)){ 
    $_files = array(); 
    if(!empty($_FILES)){ 
        /*
            파일형태는 아래와 같이 맞추어 주면된다.
        */
        $count = 0;
        foreach($_FILES as $key=>$_file){
            if( $_FILES[$key]['error'] != 0 || $_FILES[$key]['size'] < 1 ){ continue; }
            foreach($_file as $k=>$v){
                $_files[$count][$k] = $v;
            }   
            $_files[$count]['key'] = $key;
            $count++;
        }
    }
    $socket = socket_post_request('https://blog.redinfo.co.kr',$_POST,$_files);
    echo $socket;
}
?>
<form id="form" action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="POST" enctype="multipart/form-data" >
    <input type="hidden" name="input" value="input">
    <input type="hidden" name="input2" value="input2">
    <input type="file" name="files" value="">
    <input type="file" name="files2" value="">
    <input type="submit" value="전송">
</form>

 

 

 

 

 

이 포스트글이 도움이 되었나요?
4
카테고리 연관글

Comment

댓글작성

0(500) | 1(30)