Storing an object or version of an object
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.
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.
Return codes
The table below describes the HTTP return 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:
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:
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:
|
412 | Precondition Failed |
One of:
|
413 | File Too Large |
One of:
|
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 return 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 return 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()); } . . . }