Multipart Uploads

This page covers configuration and management of multipart objects objects.

Object Overview

Multipart Uploads

Endpoint, URL, and Supported Methods

Objects are managed via the storage server API at [http|https]://[hostname]:[port]/v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads.

By default, the storage server is accessible on port 8001 for the View REST API, and 8002 for the S3-compatible API. Note: storage pools are not manageable via the S3 API.

Supported methods include: GET HEAD PUT DELETE

Structure

Storage pool objects can have one of many structures depending on the type of storage pool. Currently, local disk, Amazon S3, and Azure BLOB storage pools can be configured. For assistance with configuring an Amazon S3 storage pool or an Azure BLOB storage pool, contact support.

A fully populated storage pool using local disk is shown below.:

{
    "GUID": "31a2b7b8-dc22-4e93-ad9d-5bab6d78d81b",
    "TenantGUID": "00000000-0000-0000-0000-000000000000",
    "BucketGUID": "00000000-0000-0000-0000-000000000000",
    "PoolGUID": "00000000-0000-0000-0000-000000000000",
    "NodeGUID": "eb8f61fb-2a01-4edc-974b-fbb79d1a61c8",
    "OwnerGUID": "00000000-0000-0000-0000-000000000000",
    "UploadGUID": "af08c091-c82a-4034-9a49-348850b8e5f8",
    "Key": "foo.txt",
    "StartedUtc": "2025-04-03T09:52:05.002013Z",
    "LastAccessUtc": "2025-04-03T09:52:05.002013Z",
    "CreatedUtc": "2025-04-03T09:52:05.002014Z",
    "ExpirationUtc": "2025-04-10T09:52:05.017974Z",
    "Parts": []
}

Properties:

  • GUID GUID globally unique identifier for the object
  • TenantGUID GUID globally unique identifier for the tenant
  • BucketGUID GUID globally unique identifier for the bucket
  • PoolGUID GUID globally unique identifier for the pool
  • NodeGUID GUID globally unique identifier for the node
  • OwnerGUID GUID globally unique identifier for the owner
  • UploadGUID GUID globally unique identifier for the Upload
  • Key string file name of the object
  • StartedUtc string timestamp from started, in UTC time
  • StartedUtc string timestamp from started, in UTC time
  • CreatedUtc datetime timestamp from creation, in UTC time
  • ExpirationUtc string timestamp from expiration, in UTC time
  • Parts array array of parts

Create

To create, call PUT /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads with the properties of the storage pool as defined above, using the storage server.

Note: once a storage pool has been written, it cannot be updated.

curl --location --request PUT 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads' \
--header 'Content-Type: text/plain' \
--header 'Authorization: ••••••' \
--data '{
    "Key": "foo.txt"
}'
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const createMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.create(
      "<bucket-guid>",
      {
        Key: "hello.txt",
      }
    );
    console.log(response, "Multipart upload created successfully");
  } catch (err) {
    console.log("Error creating multipart upload:", err);
  }
};

createMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def createMultipartUpload():
    object = storage.MultipartUploads.create(bucket_guid="<bucket-guid>",Key="foo.txt")
    print(object)

createMultipartUpload()

Read

To read an object by key, call GET /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key]. If the object exists, it will be returned as a JSON object in the response body. If it does not exist, a 404 will be returned with a NotFound error response.

curl --location 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/hello.txt' \
--header 'Authorization: ••••••' \
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const retrieveMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.read(
      "<bucket-guid>",
      "hello.txt"
    );
    console.log(response, "Multipart upload retrieved successfully");
  } catch (err) {
    console.log("Error retrieving multipart upload:", err);
  }
};
retrieveMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def retrieveMultipartUpload():
    object = storage.MultipartUploads.retrieve("<bucket-guid>", "foo.txt",)
    print(object)

retrieveMultipartUpload()

Read all

o read all objects, call GET /v1.0/tenants/[tenant-guid]/pools/buckets/[bucket-guid]/uploads. If the object exists, it will be returned as an array of JSON object in the response body

curl --location --request GET 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads' \
--header 'Content-Type: text/plain' \
--header 'Authorization: ••••••' \
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const retrieveMultipartUploads = async () => {
  try {
    const response = await api.multipartUpload.readAll(
      "<bucket-guid>"
    );

    console.log(response, "Multipart uploads retrieved successfully");
  } catch (err) {
    console.log("Error retrieving multipart uploads:", err);
  }
};
retrieveMultipartUploads();

import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def readAllMultipartUploads():
    object = storage.MultipartUploads.retrieve_all("<bucket-guid>")
    print(object)

readAllMultipartUploads()

Upload Part

To update, call PUT /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key]/parts?partNumber=3 with the object properties using the Configuration server

curl --location --request PUT 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/hello.txt/parts?partNumber=3' \
--header 'Content-Type: text/plain' \
--header 'Authorization: ••••••' \
--data 'Part 3.'
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const uploadPartOfMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.uploadPart(
      "<bucket-guid>",
      "hello.txt",
      1,
      "Hey There"
    );

    console.log(response, "part uploaded successfully");
  } catch (err) {
    console.log("Error uploading part:", err);
  }
};

uploadPartOfMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def uploadMultipartUpload():
    object = storage.MultipartUploads.upload_part("<bucket-guid>", "foo.txt", 1, "test")
    print(object)

uploadMultipartUpload()

Retrieve Part

To update, call GET /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key]/parts?partNumber=3 with the object properties using the Configuration server

curl --location 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/foo.txt?partNumber=1' \
--header 'Authorization: ••••••' 
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const retrievePartOfMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.readPart(
      "<bucket-guid>",
      "hello.txt",
      1
    );

    console.log(response, "part retrieved successfully");
  } catch (err) {
    console.log("Error retrieving part:", err);
  }
};

retrievePartOfMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def readMultipartUploadPart():
    object = storage.MultipartUploads.retrieve_part("<bucket-guid>", "foo.txt", 1)
    print(object)

readMultipartUploadPart()

Delete Part

To delete an object by GUID, call DELETE /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key].

curl --location --request DELETE 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/foo.txt?partNumber=1' \
--header 'Authorization: ••••••' 
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const deletePartOfMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.deletePart(
      "<bucket-guid>",
      "hello.txt",
      1
    );
    console.log(response, "part deleted successfully");
  } catch (err) {
    console.log("Error deleting part:", err);
  }
};
deletePartOfMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def deleteMultipartUploadPart():
    object = storage.MultipartUploads.delete_part("<bucket-guid>", "hello.txt", 1)
    print(object)

deleteMultipartUploadPart()

Delete Multipart Upload

To read an object by key, call GET /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key]. If the object exists, it will be returned as a JSON object in the response body. If it does not exist, a 404 will be returned with a NotFound error response.

curl --location --request DELETE 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/foo.txt' \
--header 'Authorization: ••••••' 
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const deleteMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.delete(
      "<bucket-guid>",
      "hello.txt"
    );

    console.log(response, "part deleted successfully");
  } catch (err) {
    console.log("Error deleting multipart upload:", err);
  }
};
deleteMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def deleteMultipartUpload():
    object = storage.MultipartUploads.delete("<bucket-guid>", "foo.txt")
    print(object)

deleteMultipartUpload()

Complete Multipart Upload

To complete an upload by key, call POST /v1.0/tenants/[tenant-guid]/buckets/[bucket-guid]/uploads/[key]. If the object exists, it will be returned as a JSON object in the response body. If it does not exist, a 404 will be returned with a NotFound error response.

curl --location --request POST 'http://view.homedns.org:8001/v1.0/tenants/00000000-0000-0000-0000-000000000000/buckets/00000000-0000-0000-0000-000000000000/uploads/foo.txt' \
--header 'Authorization: ••••••' 
import { ViewStorageSdk } from "view-sdk";

const api = new ViewStorageSdk(
  "http://localhost:8001/", //endpoint
  "<tenant-guid>", //tenant Id
  "default" //access key
);

const completeMultipartUpload = async () => {
  try {
    const response = await api.multipartUpload.complete(
      "<bucket-guid>",
      "hello.txt"
    );

    console.log(response, "multipart upload completed successfully");
  } catch (err) {
    console.log("Error completing multipart upload:", err);
  }
};
completeMultipartUpload();
import view_sdk
from view_sdk import storage

sdk = view_sdk.configure( access_key="default",base_url="localhost", tenant_guid= "<tenant-guid>")

def completeMultipartUpload():
    object = storage.MultipartUploads.complete_upload("<bucket-guid>", "foo.txt")
    print(object)

completeMultipartUpload()