Загрузка файла PHP SOAP

Можно ли загружать файлы с помощью PHP и SOAP?

Здесь используется код PHP:

$post = "a.txt"; $fp = fopen($post, "r"); $client = new SoapClient("http://api.4shared.com/servlet/services/DesktopApp?wsdl"); $id = $client->createUploadSessionKey("user","pass",-1); $new_id = $client->uploadStartFile("user","pass",-1, "name", 500*1024); $dcId = $client->getNewFileDataCenter("user","pass"); $sessKey = $client->createUploadSessionKey("user","pass", -1); $upload = $client->getUploadFormUrl($dcId, $sessKey); $res = $client->uploadFinishFile("user","pass", $new_id, $fp); 

Да, это возможно.

что ты уже испробовал? Используете ли вы библиотеку мыла или сами делаете? Были ли у вас проблемы с передачей файлов на работу? Если да, то что вы пытались сделать и что произошло, когда вы пытались это сделать?

edit – Проверка HTTP-трафика может быть полезным способом для отладки SOAP-серверов. Кроме того, если клиент, который вы используете, несовместим с сервером, вам, возможно, придется найти другого клиента или «бросить свой собственный». Я написал очень простой клиент, который хорошо работает с серверами SOAP, сгенерированными в рамках MS framework, и может хорошо работать с серверами Java.

Если вам нужно создать собственный клиент, это может помочь вам начать:


SimpleSoapClient.php

Расширьте это своим классом. Смотри ниже…

 <?php /** * Simple Soap Client * * Override this class to create a SOAP client. * * </pre> **/ class SimpleSoapClient { protected $host; protected $port; protected $ns; protected $url; protected $act; protected $debug; protected function Post($method, $params) { return $this->_Post($method, $params); } protected function _Post($method, $params) { $namespaces = array(); foreach($params as $p) { if (isset($p->ns)) { if ($namespaces[$p->ns]) $p->prefix = $namespaces[$p->ns]; else $p->prefix = $namespaces[$p->ns] = 'ns'.count($namespaces); } } if ($this->debug) { $cn = get_class($this); echo "\n ====== Calling $cn::$method ====== \n\nParams: "; print_r($params); } $host = $this->host; $port = $this->port; $ns = $this->ns; $url = $this->url; $act = $this->act; $fp = fsockopen($host, $port, $errno, $errstr, 30); if (!$fp) die ("Oops: $errstr ($errno)<br />\n"); $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""; foreach($namespaces as $k=>$v) $xml .= " xmlns:$v=\"$k\""; $xml .= "><s:Body><$method xmlns=\"$ns\">"; foreach($params as $k=>$v) $xml .= "<$k>$v</$k>"; $xml .= "</$method></s:Body></s:Envelope>"; $head = "POST $url HTTP/1.1\r\n" . "Host: $host\r\n" . "Content-Type: text/xml; charset=utf-8\r\n" . "Content-Length: ".strlen($xml)."\r\n" . "SOAPAction: \"$act$method\"\r\n" . "Connection: Close\r\n\r\n"; if ($this->debug) echo "\nRequest:\n\n$head$xml\n\n"; $s; fwrite($fp, $head.$xml); while (!feof($fp)) $s .= fgets($fp); fclose($fp); $s = trim(substr($s,strpos($s, "\r\n\r\n"))); if ($this->debug) echo "Response:\n\n$s\n\n"; if (strstr($s,'<error_message>')) die("\nError communicating with SOAP server.\n"); return($this->xml2assoc($s)); } private function xml2assoc($xmlstring) { $xml; if (is_object($xmlstring)) $xml = $xmlstring; else { $xml = new XMLReader(); $xml->xml($xmlstring); } $tree = null; while($xml->read()) { switch ($xml->nodeType) { case XMLReader::END_ELEMENT: return $tree; case XMLReader::ELEMENT: $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : $this->xml2assoc($xml)); if($xml->hasAttributes) while($xml->moveToNextAttribute()) $node['attributes'][$xml->name] = $xml->value; $tree[] = $node; break; case XMLReader::TEXT: case XMLReader::CDATA: $tree .= $xml->value; } } // if ($this->debug) { echo "\nTREE:\n"; print_r($tree); } return $tree; } public function DateFormat($date=null) { if (is_string($date)) $date = new DateTime($date); return implode('-',array_slice(split('-',$date ? $date->format('c') : date('c')), 0, 3)); } } class SimpleSoapType { public $prefix; public $type; public $value; public $ns; function __construct($value) { $this->value = $value; } function __toString() { $t = (isset($this->prefix) ? $this->prefix.':' : '').$this->type; $st = "<$t>"; $et = "</$t>"; if (is_array($this->value)) foreach ($this->value as $v) $r .= $st.$v.$et; else $r = $st.$this->value.$et; return $r; } protected function init() { throw('init is abstract'); } } ?> в <?php /** * Simple Soap Client * * Override this class to create a SOAP client. * * </pre> **/ class SimpleSoapClient { protected $host; protected $port; protected $ns; protected $url; protected $act; protected $debug; protected function Post($method, $params) { return $this->_Post($method, $params); } protected function _Post($method, $params) { $namespaces = array(); foreach($params as $p) { if (isset($p->ns)) { if ($namespaces[$p->ns]) $p->prefix = $namespaces[$p->ns]; else $p->prefix = $namespaces[$p->ns] = 'ns'.count($namespaces); } } if ($this->debug) { $cn = get_class($this); echo "\n ====== Calling $cn::$method ====== \n\nParams: "; print_r($params); } $host = $this->host; $port = $this->port; $ns = $this->ns; $url = $this->url; $act = $this->act; $fp = fsockopen($host, $port, $errno, $errstr, 30); if (!$fp) die ("Oops: $errstr ($errno)<br />\n"); $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""; foreach($namespaces as $k=>$v) $xml .= " xmlns:$v=\"$k\""; $xml .= "><s:Body><$method xmlns=\"$ns\">"; foreach($params as $k=>$v) $xml .= "<$k>$v</$k>"; $xml .= "</$method></s:Body></s:Envelope>"; $head = "POST $url HTTP/1.1\r\n" . "Host: $host\r\n" . "Content-Type: text/xml; charset=utf-8\r\n" . "Content-Length: ".strlen($xml)."\r\n" . "SOAPAction: \"$act$method\"\r\n" . "Connection: Close\r\n\r\n"; if ($this->debug) echo "\nRequest:\n\n$head$xml\n\n"; $s; fwrite($fp, $head.$xml); while (!feof($fp)) $s .= fgets($fp); fclose($fp); $s = trim(substr($s,strpos($s, "\r\n\r\n"))); if ($this->debug) echo "Response:\n\n$s\n\n"; if (strstr($s,'<error_message>')) die("\nError communicating with SOAP server.\n"); return($this->xml2assoc($s)); } private function xml2assoc($xmlstring) { $xml; if (is_object($xmlstring)) $xml = $xmlstring; else { $xml = new XMLReader(); $xml->xml($xmlstring); } $tree = null; while($xml->read()) { switch ($xml->nodeType) { case XMLReader::END_ELEMENT: return $tree; case XMLReader::ELEMENT: $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : $this->xml2assoc($xml)); if($xml->hasAttributes) while($xml->moveToNextAttribute()) $node['attributes'][$xml->name] = $xml->value; $tree[] = $node; break; case XMLReader::TEXT: case XMLReader::CDATA: $tree .= $xml->value; } } // if ($this->debug) { echo "\nTREE:\n"; print_r($tree); } return $tree; } public function DateFormat($date=null) { if (is_string($date)) $date = new DateTime($date); return implode('-',array_slice(split('-',$date ? $date->format('c') : date('c')), 0, 3)); } } class SimpleSoapType { public $prefix; public $type; public $value; public $ns; function __construct($value) { $this->value = $value; } function __toString() { $t = (isset($this->prefix) ? $this->prefix.':' : '').$this->type; $st = "<$t>"; $et = "</$t>"; if (is_array($this->value)) foreach ($this->value as $v) $r .= $st.$v.$et; else $r = $st.$this->value.$et; return $r; } protected function init() { throw('init is abstract'); } } ?> в <?php /** * Simple Soap Client * * Override this class to create a SOAP client. * * </pre> **/ class SimpleSoapClient { protected $host; protected $port; protected $ns; protected $url; protected $act; protected $debug; protected function Post($method, $params) { return $this->_Post($method, $params); } protected function _Post($method, $params) { $namespaces = array(); foreach($params as $p) { if (isset($p->ns)) { if ($namespaces[$p->ns]) $p->prefix = $namespaces[$p->ns]; else $p->prefix = $namespaces[$p->ns] = 'ns'.count($namespaces); } } if ($this->debug) { $cn = get_class($this); echo "\n ====== Calling $cn::$method ====== \n\nParams: "; print_r($params); } $host = $this->host; $port = $this->port; $ns = $this->ns; $url = $this->url; $act = $this->act; $fp = fsockopen($host, $port, $errno, $errstr, 30); if (!$fp) die ("Oops: $errstr ($errno)<br />\n"); $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""; foreach($namespaces as $k=>$v) $xml .= " xmlns:$v=\"$k\""; $xml .= "><s:Body><$method xmlns=\"$ns\">"; foreach($params as $k=>$v) $xml .= "<$k>$v</$k>"; $xml .= "</$method></s:Body></s:Envelope>"; $head = "POST $url HTTP/1.1\r\n" . "Host: $host\r\n" . "Content-Type: text/xml; charset=utf-8\r\n" . "Content-Length: ".strlen($xml)."\r\n" . "SOAPAction: \"$act$method\"\r\n" . "Connection: Close\r\n\r\n"; if ($this->debug) echo "\nRequest:\n\n$head$xml\n\n"; $s; fwrite($fp, $head.$xml); while (!feof($fp)) $s .= fgets($fp); fclose($fp); $s = trim(substr($s,strpos($s, "\r\n\r\n"))); if ($this->debug) echo "Response:\n\n$s\n\n"; if (strstr($s,'<error_message>')) die("\nError communicating with SOAP server.\n"); return($this->xml2assoc($s)); } private function xml2assoc($xmlstring) { $xml; if (is_object($xmlstring)) $xml = $xmlstring; else { $xml = new XMLReader(); $xml->xml($xmlstring); } $tree = null; while($xml->read()) { switch ($xml->nodeType) { case XMLReader::END_ELEMENT: return $tree; case XMLReader::ELEMENT: $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : $this->xml2assoc($xml)); if($xml->hasAttributes) while($xml->moveToNextAttribute()) $node['attributes'][$xml->name] = $xml->value; $tree[] = $node; break; case XMLReader::TEXT: case XMLReader::CDATA: $tree .= $xml->value; } } // if ($this->debug) { echo "\nTREE:\n"; print_r($tree); } return $tree; } public function DateFormat($date=null) { if (is_string($date)) $date = new DateTime($date); return implode('-',array_slice(split('-',$date ? $date->format('c') : date('c')), 0, 3)); } } class SimpleSoapType { public $prefix; public $type; public $value; public $ns; function __construct($value) { $this->value = $value; } function __toString() { $t = (isset($this->prefix) ? $this->prefix.':' : '').$this->type; $st = "<$t>"; $et = "</$t>"; if (is_array($this->value)) foreach ($this->value as $v) $r .= $st.$v.$et; else $r = $st.$this->value.$et; return $r; } protected function init() { throw('init is abstract'); } } ?> 

ExampleSoapClient.php

Это на самом деле продукт [1] мыльный клиент, переименованный в «Пример».

 <?php require_once 'SimpleSoapClient.php'; /** * Example Soap Client **/ class ExampleSoapClient extends SimpleSoapClient { function __construct() { $this->host = 'connect.example.com'; $this->port = 80; $this->ns = "https://{$this->host}/connect"; $this->url = "http://{$this->host}/svc/connect.svc"; $this->act = "{$this->ns}/IConnect/"; $this->debug = true; } protected function Post ($method, $params) { $params['apiKey'] = 'abcdef1234567890'; return $this->_Post($method, $params); } private function returnMulti($d) { foreach($d[0]['value'][0]['value'][0]['value'][0]['value'] as $v) $r[] = $v['value']; return $r; } private function returnSingle($d) { $r = $d[0]['value'][0]['value'][0]['value'][0]['value']; return $r; } private function returnMultiPairs($d) { $d = $this->returnMulti($d); foreach ($d as $v) $r[$v[0]['value']] = $v[1]['value']; return $r; } /** * Get Property Categories * * **/ public function GetPropertyCategories() { $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnMulti($d); } /** * Get Property IDs (undocumented) * * @param dateTime $lastMod Last modified date * **/ public function GetPropertyIDs($lastMod) { $lastMod = $this->DateFormat($lastMod); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnMulti($d); } /** * Get Property (undocumented) * * @param string $propertyID Property ID * **/ public function GetProperty($propertyID) { $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnSingle($d); } /** * Get Property IDs by Category * * @param int $propertyCategory Property category to get IDs for * **/ public function GetPropertyIDsByCategory($propertyCategory) { $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnMulti($d); } /** * Get Rates * * @param int $propertyID Property ID to get rates for * @param string $rateType Currently unused * @param int $los Length of stay - 1 (daily), 7 (weekly), or 30 (monthly) * @param string $startDate Beginning of period to retrieve data for * @param string $endDate End of period to retrieve data for * @param string $currency Currently 'USD' only * **/ public function GetRates($propertyID, $rateType, $los, $startDate, $endDate, $currency) { $startDate = $this->DateFormat($startDate); $endDate = $this->DateFormat($endDate); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnMultiPairs($d); } /** * Get Availability * * @param int $propertyID Property ID to get availability for * @param string $rateType Currently unused * @param string $startDate Beginning of period to retrieve data for * @param string $endDate End of period to retrieve data for * **/ public function GetAvailability($propertyID, $rateType, $startDate, $endDate) { $startDate = $this->DateFormat($startDate); $endDate = $this->DateFormat($endDate); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnMultiPairs($d); } /** * Set Rates * * @param int $propertyID Property ID to set rates for * @param string $rateType Currently unused * @param int $los Length of stay - 1 (daily), 7 (weekly), or 30 (monthly) * @param array $effDates Effective dates * @param array $rates Rate for each date * @param string $currency Currently 'USD' only * **/ public function SetRates($propertyID, $rateType, $los, $effDates, $rates, $currency) { if (!get_class($effDates) == 'msDateTime') $effDates = new msDateTime($effDates); if (!get_class($rates) == 'msDecimal') $rates = new msDecimal($rates); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $d; } /** * Set Availability * * @param int $propertyID Property ID to set availability for * @param array $effDates Effective dates * @param array $numAvailabile Available units for each date [sic] * **/ public function SetAvailability($propertyID, $effDates, $numAvailabile) // notice spelling: numAvailabile { if (!get_class($effDates) == 'msDateTime') $effDates = new msDateTime($effDates); if (!get_class($numAvailabile) == 'msInt') $numAvailabile = new msInt($numAvailabile); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $d; } /** * Set Rates and Availability * * @param int $propertyID Property ID to set rates and availability for * @param string $rateType Currently unused * @param int $los Length of stay - 1 (daily), 7 (weekly), or 30 (monthly) * @param array $effDates Effective dates * @param array $rates Rate for each date * @param string $currency Currently 'USD' only * @param array $numAvailabile Available units for each date [sic] * **/ public function SetRatesAndAvailability($propertyID, $rateType, $los, $effDates, $rates, $currency, $numAvailabile) { if (!get_class($effDates) == 'msDateTime') $effDates = new msDateTime($effDates); if (!get_class($rates) == 'msDecimal') $rates = new msDecimal($rates); if (!get_class($numAvailabile) == 'msInt') $numAvailabile = new msInt($numAvailabile); $d = $this->Post(__FUNCTION__, get_defined_vars()); return $d; } /** * Get Booking * * @param int $bookingID ID of Booking to retrieve * **/ public function GetBooking($bookingID) { $d = $this->Post(__FUNCTION__, get_defined_vars()); return $this->returnSingle($d); } /** * Make Booking * * @param bcBooking $booking Booking object * @param bool $infoOnly If true, simulate booking without actually booking anything * **/ public function MakeBooking($booking, $infoOnly) { $d = $this->Post(__FUNCTION__, get_defined_vars()); return $d; // $this->returnMulti($d); } } /** * base soap type - MS array serialization **/ class msSoapType extends SimpleSoapType { function __construct($value) { $this->ns = 'http://schemas.microsoft.com/2003/10/Serialization/Arrays'; parent::__construct($value); } } /** * dateTime soap type - MS array serialization **/ class msDateTime extends msSoapType { function __construct($value) { $this->type = 'dateTime'; parent::__construct($value); if (is_array($value)) foreach ($value as $k=>$v) $this->value[$k] = SimpleSoapClient::DateFormat($v); else $this->value = SimpleSoapClient::DateFormat($value); } } /** * decimal soap type - MS array serialization **/ class msDecimal extends msSoapType { function __construct($value) { $this->type = 'decimal'; parent::__construct($value); } } /** * int soap type - MS array serialization **/ class msInt extends msSoapType { function __construct($value) { $this->type = 'int'; parent::__construct($value); } } ?> 

[1] – Не могу посмотреть качество продукции, но я использую это и другие, подобные им на некоторых рабочих местах cron и PHP-сайтах, и он работает хорошо 🙂

Да.

Вы можете передавать любые данные, которые вам нравятся. Вам нужно всего лишь base64 кодировать двоичные данные. Он преобразует его в символы ascii. Затем вы можете перенести его как обычную строковую переменную. Единственное, что вам нужно, чтобы быть осторожным, – это пределы сервера.

С уважением