PHP에서 다른 서버로 파일을 전송하는 방법에는 크게 CURL 통신과 소켓통신이 있다.
솔직히 회사에서 사용한다면 CURL 통신을 추천하지만 부득이하게 CURL 통신으로 안될경우
소켓통신을 사용하는것을 추천한다.
소켓통신이 사용하는 방법이 까다롭고, 서버에 따라 잘 안되는 경우도 있는것같다.
이번에 만든 함수같은 경우 전에 다른 서버에서 사용했던 함수였는데 이상하게도
현재 서버에서는 500 에러가 계속 발생되어 삽질을 많이 하면서 수정을 했다.
따라서 모든 서버에서 된다는 보장은 못하겠다.
일단 소스코드는 아래와 같다.
<?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>