Example #1
0
 /**
  * Save an Object into Object Storage.
  *
  * This takes an \OpenStack\ObjectStore\v1\Resource\Object
  * and stores it in the given container in the present
  * container on the remote object store.
  *
  * @param object   $obj  \OpenStack\ObjectStore\v1\Resource\Object The object to
  *                       store.
  * @param resource $file An optional file argument that, if set, will be
  *                       treated as the contents of the object.
  *
  * @return boolean true if the object was saved.
  *
  * @throws \OpenStack\Common\Transport\Exception\LengthRequiredException      if the Content-Length could not be
  *                                                                            determined and chunked encoding was
  *                                                                            not enabled. This should not occur for
  *                                                                            this class, which always automatically
  *                                                                            generates Content-Length headers.
  *                                                                            However, subclasses could generate
  *                                                                            this error.
  * @throws \OpenStack\Common\Transport\Exception\UnprocessableEntityException if the checksum passed here does not
  *                                                                            match the checksum calculated remotely.
  * @throws \OpenStack\Common\Exception                                        when an unexpected (usually
  *                                                                            network-related) error condition arises.
  */
 public function save(Object $obj, $file = null)
 {
     if (empty($this->token)) {
         throw new Exception('Container does not have an auth token.');
     }
     if (empty($this->url)) {
         throw new Exception('Container does not have a URL to send data.');
     }
     //$url = $this->url . '/' . rawurlencode($obj->name());
     $url = self::objectUrl($this->url, $obj->name());
     // See if we have any metadata.
     $headers = [];
     $md = $obj->metadata();
     if (!empty($md)) {
         $headers = self::generateMetadataHeaders($md, Container::METADATA_HEADER_PREFIX);
     }
     // Set the content type.
     $headers['Content-Type'] = $obj->contentType();
     // Add content encoding, if necessary.
     $encoding = $obj->encoding();
     if (!empty($encoding)) {
         $headers['Content-Encoding'] = rawurlencode($encoding);
     }
     // Add content disposition, if necessary.
     $disposition = $obj->disposition();
     if (!empty($disposition)) {
         $headers['Content-Disposition'] = $disposition;
     }
     // Auth token.
     $headers['X-Auth-Token'] = $this->token;
     // Add any custom headers:
     $moreHeaders = $obj->additionalHeaders();
     if (!empty($moreHeaders)) {
         $headers += $moreHeaders;
     }
     if (empty($file)) {
         // Now build up the rest of the headers:
         $headers['Etag'] = $obj->eTag();
         // If chunked, we set transfer encoding; else
         // we set the content length.
         if ($obj->isChunked()) {
             // How do we handle this? Does the underlying
             // stream wrapper pay any attention to this?
             $headers['Transfer-Encoding'] = 'chunked';
         } else {
             $headers['Content-Length'] = $obj->contentLength();
         }
         $response = $this->client->put($url, $obj->content(), ['headers' => $headers]);
     } else {
         // Rewind the file.
         rewind($file);
         // XXX: What do we do about Content-Length header?
         //$headers['Transfer-Encoding'] = 'chunked';
         $stat = fstat($file);
         $headers['Content-Length'] = $stat['size'];
         // Generate an eTag:
         $hash = hash_init('md5');
         hash_update_stream($hash, $file);
         $etag = hash_final($hash);
         $headers['Etag'] = $etag;
         // Not sure if this is necessary:
         rewind($file);
         $response = $this->client->put($url, $file, ['headers' => $headers]);
     }
     if ($response->getStatusCode() != 201) {
         throw new Exception('An unknown error occurred while saving: ' . $response->status());
     }
     return true;
 }