PHP SOAP文件上传

时间:2010-09-07 23:14:34

标签: 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);

2 个答案:

答案 0 :(得分: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] soap客户端重命名为'Example'。

<?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网站上使用它和其他人喜欢它并且它运行良好:)

答案 1 :(得分:1)

是的。

您可以传输您喜欢的任何数据。您只需要对二进制数据进行base64编码。它会将其转换为ascii字符。然后你可以像普通的字符串变量一样传输它。唯一需要注意的是服务器限制。

此致