2010-09-07 59 views
1

是否可以使用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); 

回答

3

是的,這是可能的。

你到目前爲止嘗試過什麼?你使用肥皂庫還是自己推出?你有沒有遇到任何問題讓文件傳輸工作?如果是這樣,你試圖做什麼,當你嘗試做什麼?

編輯 - 檢查HTTP流量可能是調試SOAP服務器的有用方法。另外,如果您使用的客戶端與服務器不兼容,則可能需要找到另一個客戶端或「自己推出」。我寫了一個非常簡單的客戶端,可以很好地與MS框架生成的SOAP服務器配合使用,它也可以與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'); } 
} 

?> 

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的網站,它的工作以及:)

+0

http://help.4shared.com/index.php/SOAP_API這裏是用java的例子,但我不能文件到端口添加到PHP。 java代碼:http://4shared-api.googlecode.com/svn/trunk/java/demo/src/com/pmstation/api/demo/UploadDemo.java – Hajimba 2010-09-07 23:26:56

+0

你可以發佈PHP端口的代碼嗎?還有,你看看這個:http://php.net/manual/en/book.soap.php – 2010-09-07 23:30:14

+0

好的。有我的PHP代碼,但你將如何添加文件,在wsdl沒有定義的方式java實例正在做它。 http://pastebin.com/H1R78AZY – Hajimba 2010-09-07 23:34:10

1

是的。

您可以傳輸任何你喜歡的數據。你只需要base64編碼二進制數據。它會將其轉換爲ascii字符。然後你可以像普通的字符串變量一樣傳輸它。唯一需要注意的是服務器限制。

問候