Storing an object or version of an object

Content Platform Tenant Management Help

Version
9.7.x
File Size
4269 KB
Audience
anonymous
Part Number
MK-95HCPH002-19

You use the HTTP PUT method to store an object or new version of an existing object in a namespace. You can optionally use this method to store the object or version data and custom metadata in a single operation.

To store versions, the namespace must be configured to allow versioning. When versioning is enabled, storing an object with the same name as an existing object creates a new version of the object.

You can store new versions of any object, including multipart objects created by using the multipart upload feature of the S3-compatible API, as long as the object is not under retention or on hold. You cannot store new versions of an object that is under retention or on hold.

By default, a new object inherits several metadata values from namespace configuration settings. A new version of an object inherits the metadata values of the previous version of the object. In either case, you can override this default metadata when you store the object or version.

Tip: To store very large objects, use the S3-compatible API. With the S3 compatible API, you can break up the data for an object into multiple parts and upload the parts to HCP individually. The process of creating an object by uploading the data in parts is called multipart upload. The result of a multipart upload is a single object that behaves in the same way as objects for which all the data was stored by means of a single PUT object request.

Access permission

To store an object in a namespace, you need write permission for the namespace.

To store a version of an object in a namespace, you need write permission for the object or namespace.

Request header

PUT /rest/directory/file?type=whole-object&annotaton=annotation_location HTTP/1.1

The PUT request to store an object or version has these elements:

  • If you are accessing the namespace as an authenticated user, an Authorization header
  • A URL specifying the location in which to store the object
  • A body containing the fixed-content data to be stored in the namespace

You can use a single request to store object data and a single annotation. To do this, the request body must contain the fixed-content data to be stored, followed by the annotation content, with no delimiter between them. Additionally, specify the request elements in the next table.

Parameter Required Description
directory Yes Folder name.
file Yes Name of the file, including file extension.
type No Use the value whole-object to retrieve a single object or version data.
annotation No Use a value of the name of the annotation. You can omit this parameter for the default annotation.Used in conjunction with the type parameter.

Response headers

The list below describes request-specific HTTP response headers returned by a successful request.

ETag
The ETag of the object or version enclosed in double quotation marks ("). This header is returned only if the object has an ETag.
X-HCP-CustomMetadata Hash
The cryptographic hash algorithm HCP uses and the cryptographic hash value of the stored annotation, in this format:
X-HCP-CustomMetadataHash: hash-algorithm hash-value
You can use the returned hash value to verify that the content of the stored annotation is the same as the annotation content you sent. To do this, compare this value with a hash value that you generate from the original annotation content.
This header is returned only if the request contains both data and custom metadata.
X-HCP-Hash
The cryptographic hash algorithm HCP uses, along with the cryptographic hash value stored for the object, in this format:
X-HCP-Hash: hash-algorithmhash-value
You can use the returned hash value to verify that the stored data is the same as the data you sent. To perform the verification, compare this value with a hash value that you generate from the original data.
The
X-HCP-Hash
header is not returned for multipart objects.
X-HCP-VersionId
The version ID of the object.

Response body

Not applicable.

Status codes

The table below describes the HTTP status codes that have specific meaning for this request.

Code Meaning Description
201 Created HCP successfully stored the object. If versioning is enabled and an object with the same name already exists, HCP created a new version of the object.
304 Not Modified A request to store a new version of an existing object specified an If-Modified-Since header, and the change time of the current version is at or before the time specified in the header.
400 Bad Request

One of:

  • The URL in the request is not well-formed.
  • The request has a Content-Encoding header that specifies gzip, but the data is not in Gzip compressed format.
  • The request has a type=whole-object query parameter, and either:
    • The request does not have an X-HCP-Size header.
    • The X-HCP-Size header value is greater than the content length.
  • The namespace has custom metadata XML checking enabled, and the request included an annotation that is not well-formed XML.

    If the request that causes this error contains both object data and an annotation, HCP creates an empty object before it returns the error. To resolve this issue, you can either:

    • Fix the annotation and retry the request.
    • Store the object again without the annotation, thereby replacing the empty object. You can then fix the annotation at a later time and add it in a separate request.
  • A request to store a version of an existing object included an If-Match or If-None-Match header and the object does not yet have an ETag.
  • The request contains an unsupported query parameter or an invalid value for a query parameter.

If more information about the error is available, the HTTP response headers include the HCP product-specific X‑HCP-ErrorMessage header.

403 Forbidden

One of:

  • The Authorization header or hcp-ns-auth cookie specifies invalid credentials.
  • The namespace requires client authentication, and the request does not have an Authorization header or hcp-ns-auth cookie.
  • The user does not have write permission.
  • For a request to store a version of an existing object, the object is under retention.
  • The namespace does not exist.
  • The access method (HTTP or HTTPS) is disabled.

If more information about the error is available, the HTTP response headers include the HCP product-specific X‑HCP-ErrorMessage header.

409 Conflict

One of:

  • HCP could not store the object in the namespace because the object already exists and versioning is not enabled.
  • HCP could not store a new version of an existing object because another version is currently being added.
  • HCP could not evaluate conditional headers because a version of the object is currently being added.
412 Precondition Failed

One of:

  • A request to store a new version of an object specified an If-Match header, and the ETag of the existing object does not match the value in the header.
  • A request to store a new version of an existing object specified an If-None-Match header, and the ETag of the existing object matches the value in the header.
  • A request to store a new version of an existing object specified an If-Unmodified-Since header, and the change time of the existing object is after the time specified in the header.
413 File Too Large

One of:

  • Not enough space is available to store the object. Try the request again after objects or versions are deleted from the namespace or the namespace capacity is increased.
  • The request is trying to store an object that is larger than 2 TB. HCP cannot store objects larger than 2 TB.
  • The request is trying to store custom metadata that is larger than 1 GB. HCP cannot store custom metadata larger than 1 GB.
415 Unsupported Media Type The request has a Content-Encoding header with a value other than gzip.

Storing an object or object version

Here is a sample HTTP PUT request that stores a new object or new version of an object named Q2_2020.ppt in the quarterly_rpts directory.

Request with curl command line

curl -k -iT Q2_2020.ppt
    -H "Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d"
    "https://finance.europe.hcp.example.com/rest/quarterly_rpts/Q2_2020.ppt"

Request in Python using PycURL

import pycurl
import os
filehandle = open("Q2_2020.ppt", 'rb')
curl = pycurl.Curl()
curl.setopt(pycurl.HTTPHEADER, ["Authorization: HCP
    bXl1c2Vy:3f3c6784e97531774380db177774ac8d"])
curl.setopt(pycurl.URL, "https://finance.europe.hcp.example.com/ \
    rest/quarterly_rpts/Q2_2020.ppt")
curl.setopt(pycurl.SSL_VERIFYPEER, 0)
curl.setopt(pycurl.SSL_VERIFYHOST, 0)
curl.setopt(pycurl.UPLOAD, 1)
curl.setopt(pycurl.INFILESIZE, os.path.getsize("Q1_2020.ppt"))
curl.setopt(pycurl.READFUNCTION, filehandle.read)
curl.perform()
print curl.getinfo(pycurl.RESPONSE_CODE)
curl.close()
filehandle.close()

Request headers

PUT /rest/quarterly_rpts/Q2_2020.ppt HTTP/1.1
Host: /finance.europe.hcp.example.com
Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d
Content-Length: 678400

Response headers

HTTP/1.1 201 Created
X-HCP-ServicedBySystem: hcp.example.com
ETag: "9c604138ffb0f308a8552a3752e5a1be"
Location: /rest/quarterly_rpts/Q2_2020.ppt
X-HCP-VersionId: 79885459513089
X-HCP-VersionCreateTimeMilliseconds: 1494364634616
X-HCP-Hash: SHA-256 E830B86212A66A792A79D58BB185EE63A4FADA76BB8A1...
X-HCP-Time: 1334858878
Content-Length: 0

Sending object or version data with an annotation (Unix)

Here is a Unix command line that uses an HTTP PUT request to store the object data and an annotation for a file named Q2_2020.ppt. The request stores the object in the quarterly_rpts directory.

The cat command appends the contents of the Q2_2020-custom-metadata.xml file to the contents of the Q2_2020.ppt file. The result is piped to a curl command that sends the data to HCP and saves the content of Q2_2020-custom-metadata.xml in an annotation named report_data.

Unix command line

cat Q2_2020.ppt Q2_2020-custom-metadata.xml | curl -k -iT -
    -H "X-HCP-Size: `stat -c %s Q2_2020.ppt`"
    -H "Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d"
    "https://finance.europe.hcp.example.com/rest/quarterly_rpts/Q2_2020.ppt
    ?type=whole-object&annotation=report_data"

Request headers

PUT /rest/quarterly_rpts/Q2_2020.ppt?type=whole-object&annotaton=report_data HTTP/1.1
Host: /finance.europe.hcp.example.com
Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d
X-HCP-Size: 678685
Content-Length: 678900

Response headers

HTTP/1.1 201 Created
X-HCP-ServicedBySystem: hcp.example.com
ETag: "9c604138ffb0f308a8552a3752e5a1be"
Location: /rest/quarterly_rpts/Q2_2020.ppt
X-HCP-VersionId: 79885459513089
X-HCP-VersionCreateTimeMilliseconds: 1494364634616
X-HCP-Hash: SHA-256 E830B86212A66A792A79D58BB185EE63A4FADA76BB8A1...
X-HCP-CustomMetadataHash: SHA-256 86212A6692A79D5B185EE63A4DA76BBC...
X-HCP-Time: 1334862493
Content-Length: 0

Sending object or version data with an annotation (Java)

Here is the partial implementation of a Java class named WholeIO. The implementation shows the WriteToHCP method, which uses a single HTTP PUT request to store data and an annotation for an object (or version).

This example assumes that the applicable imports are included in the full class implementation.

public class WholeIO {
  .
  .
  .
void WriteToHCP() throws Exception {
    /*
     * Set up the PUT request to store both object data and an
     * annotation.
     * This method assumes that the HTTP client has already been
     * initialized.
     */
    HttpPut httpRequest = new HttpPut(sHCPURLFilePath +
      "?type=whole-object");

    // Construct the Whole I/O Sequenced Stream with the object data
    // and annotation.
    FileInputStream dataFileStream = new FileInputStream(sBaseFileName);


    FileInputStream customMetadataStream =
      new FileInputStream(sBaseFileName + ".cm");

    SequenceInputStream wholeIOStream = new SequenceInputStream(
        dataFileStream, customMetadataStream);

    // Point the HttpRequest to the input stream.
    httpRequest.setEntity(new InputStreamEntity(wholeIOStream, -1));

    // Put the size of the data object data into the X-HCP-Size header.
    httpRequest.setHeader("X-HCP-Size",
      String.valueOf(dataFileStream.available()));

    // Create the HTTP Authorization Header.
    httpRequest.setHeader(HCPUtils.HTTP_AUTH_HEADER, "HCP " +
       sEncodedUserName + ":" + sEncodedPassword);

    /*
     * Now execute the PUT request.
     */
    HttpResponse httpResponse = mHttpClient.execute(httpRequest);

    // If the status code is anything BUT 200 range indicating success,
    // throw an exception.
    if (2 != (int)(httpResponse.getStatusLine().getStatusCode() / 100))
    {
      // Clean up after ourselves and release the HTTP connection to the
      // connection manager.
      EntityUtils.consume(httpResponse.getEntity())

      wholeIOStream.close();
      dataFileStream.close();
      customMetadataStream.close();

      throw new HttpResponseException(
         httpResponse.getStatusLine().getStatusCode(),
         "Unexpected status returned from " + httpRequest.getMethod()
         + " (" + httpResponse.getStatusLine().getStatusCode() + ": "
         + httpResponse.getStatusLine().getReasonPhrase() + ")");
    }

    // Clean up after ourselves and release the HTTP connection to the
    // connection manager.
    EntityUtils.consume(httpResponse.getEntity());

    wholeIOStream.close();
    dataFileStream.close();
    customMetadataStream.close();

  }
  .
  .
  .
}

Sending object data in compressed format (Unix)

Here is a Unix command line that uses the gzip utility to compress the

Q2_2020.ppt file and then pipes the compressed output to a curl command. The curl command makes an HTTP PUT request that sends the data and tells HCP that the data is compressed.

Request with gzip and curl commands

gzip -c Q2_2020.ppt |
    curl -k -T -
    -H "Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d"
    -H "Content-Encoding: gzip"
    "https://finance.europe.hcp.example.com/rest/quarterly_rpts/Q2_2020.ppt"

Request headers

PUT /rest/quarterly_rpts/Q2_2020.ppt HTTP/1.1
Host: /finance.europe.hcp.example.com
Authorization: HCP bXl1c2Vy:3f3c6784e97531774380db177774ac8d
Content-Length: 678400
Transfer-Encoding: chunked
Content-Encoding: gzip
Expect: 100-continue

Response headers

HTTP/1.1 201 Created
X-HCP-ServicedBySystem: hcp.example.com
ETag: "9c604138ffb0f308a8552a3752e5a1be"
Location: /rest/quarterly_rpts/Q2_2020.ppt
X-HCP-VersionId: 79885459513089
X-HCP-VersionCreateTimeMilliseconds: 1494364634616
X-HCP-Hash: SHA-256 E830B86212A66A792A79D58BB185EE63A4FADA76BB8A1...
X-HCP-Time: 1334862478
Content-Length: 0

Sending object data in compressed format (Java)

Here is the partial implementation of a Java class named HTTPCompression. The implementation shows the WriteToHCP method, which stores an object (or version) in an HCP namespace. The method compresses the data before sending it and uses the Content-Encoding header to tell HCP that the data is compressed.

The WriteToHCP method uses the GZIPCompressedInputStream helper class.

import org.apache.http.client.methods.HttpPut;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import com.hds.hcp.examples.GZIPCompressedInputStream;

class HTTPCompression {
   .
   .
   .
void WriteToHCP() throws Exception {

   /*
    * Set up the PUT request.
    *
    * This method assumes that the HTTP client has already been
     * initialized.
     */
    HttpPut httpRequest = new HttpPut(sHCPFilePath);

   // Indicate that the content encoding is gzip.
   httpRequest.setHeader("Content-Encoding", "gzip");

   // Open an input stream to the file that will be sent to HCP.
   // This file will be processed by the GZIPCompressedInputStream to
   // produce gzip-compressed content when read by the Apache HTTP client.
    GZIPCompressedInputStream compressedInputFile
      = new GZIPCompressedInputStream(new FileInputStream(
                                      sBaseFileName + ".toHCP"));

   // Point the HttpRequest to the input stream.
   httpRequest.setEntity(new InputStreamEntity(compressedInputFile, -1));

   // Create the HCP Authorization header.
   httpRequest.setHeader("Authorization", "HCP " + sEncodedUserName
                          + ":" + sEncodedPassword);

   /*
    * Now execute the PUT request.
    */
   HttpResponse httpResponse = mHttpClient.execute(httpRequest);

   /*
    * Process the HTTP response.
    */
   // If the status code is anything but in the 200 range indicating
   // success, throw an exception.
   if (2 != (int)(httpResponse.getStatusLine().getStatusCode() / 100))
   {
      // Clean up after ourselves and release the HTTP connection to the
      // connection manager.
      EntityUtils.consume(httpResponse.getEntity());

      throw new Exception("Unexpected HTTP status code: " +
      httpResponse.getStatusLine().getStatusCode() + " (" +
      httpResponse.getStatusLine().getReasonPhrase() + ")");
   }

   // Clean up after ourselves and release the HTTP connection to the
   // connection manager.
   EntityUtils.consume(httpResponse.getEntity());
}
   .
   .
   .
}