Compose objects

Overview

This page shows you how to compose Cloud Storage objects into a singleobject. A compose request takes between 1 and 32 objects andcreates a new,composite object. The composite object is a concatenationof the source objects in the order they were specified in the request.

Note the following when composing objects:

  • The source objects are unaffected by the composition process. If theyare meant to be temporary, you mustdelete them once you've successfullycompleted the composition.
  • Because other storage classes are subject toearly deletion fees, youshould always useStandard storage for temporary objects.
  • Frequent deletions associated with compose can increase your storage billsignificantly if your bucket has data protection features enabled. Considerdisablingsoft delete on buckets with high rates of composeoperations. WithObject Versioning, specify the object versions whendeleting source objects to permanently delete them and avoid their becomingnoncurrent objects.

Required roles

To get the permissions that you need to compose objects, ask youradministrator to grant you the Storage Object User (roles/storage.objectUser)IAM role on the bucket. Thispredefined role contains thepermissions required to compose objects. To see the exact permissions that arerequired, expand theRequired permissions section:

Required permissions

  • storage.objects.create
  • storage.objects.delete
    • This permission is only required if you want to give the object youcompose the same name as an object that already exists in the bucket.
  • storage.objects.get
  • storage.objects.list
    • This permission is only required if you want to usewildcards to compose objects with a commonprefix without having to list each object separately in your Google Cloud CLIcommand.

If you want to set aretention configuration for the objectyou compose, you'll also need thestorage.objects.setRetention permission. Toget this permission, ask your administrator to grant you the Storage ObjectAdmin (roles/storage.objectAdmin) role instead of the Storage Object User(roles/storage.objectUser) role.

You can also get these permissions with other predefined roles orcustom roles.

For information about granting roles on buckets, seeSet and manage IAM policies on buckets.

Create a composite object

Command line

Use thegcloud storage objects compose command:

gcloud storage objects compose gs://BUCKET_NAME/SOURCE_OBJECT_1 gs://BUCKET_NAME/SOURCE_OBJECT_2 gs://BUCKET_NAME/COMPOSITE_OBJECT_NAME

Where:

  • BUCKET_NAME is the name of the bucket thatcontains the source objects.
  • SOURCE_OBJECT_1 andSOURCE_OBJECT_2 are the names of the sourceobjects to use in the object composition.
  • COMPOSITE_OBJECT_NAME is the name you aregiving to the result of the object composition.
Note: You can also use awildcard to compose objects with a commonprefix without having to list each object separately in the command.

Client libraries

C++

For more information, see theCloud StorageC++ API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

namespacegcs=::google::cloud::storage;using::google::cloud::StatusOr;[](gcs::Clientclient,std::stringconst&bucket_name,std::stringconst&destination_object_name,std::vector<gcs::ComposeSourceObject>const&compose_objects){StatusOr<gcs::ObjectMetadata>composed_object=client.ComposeObject(bucket_name,compose_objects,destination_object_name);if(!composed_object)throwstd::move(composed_object).status();std::cout <<"Composed new object " <<composed_object->name()            <<" in bucket " <<composed_object->bucket()            <<"\nFull metadata: " <<*composed_object <<"\n";}

C#

For more information, see theCloud StorageC# API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

usingGoogle.Apis.Storage.v1.Data;usingGoogle.Cloud.Storage.V1;usingSystem;usingSystem.Collections.Generic;publicclassComposeObjectSample{publicvoidComposeObject(stringbucketName="your-bucket-name",stringfirstObjectName="your-first-object-name",stringsecondObjectName="your-second-object-name",stringtargetObjectName="new-composite-object-name"){varstorage=StorageClient.Create();varsourceObjects=newList<ComposeRequest.SourceObjectsData>{newComposeRequest.SourceObjectsData{Name=firstObjectName},newComposeRequest.SourceObjectsData{Name=secondObjectName}};//You could add as many sourceObjects as you want here, up to the max of 32.storage.Service.Objects.Compose(newComposeRequest{SourceObjects=sourceObjects,Destination=newGoogle.Apis.Storage.v1.Data.Object{ContentType="text/plain"}},bucketName,targetObjectName).Execute();Console.WriteLine($"New composite file {targetObjectName} was created in bucket {bucketName}"+$" by combining {firstObjectName} and {secondObjectName}.");}}

Go

For more information, see theCloud StorageGo API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

import("context""fmt""io""time""cloud.google.com/go/storage")// composeFile composes source objects to create a composite object.funccomposeFile(wio.Writer,bucket,object1,object2,toObjectstring)error{// bucket := "bucket-name"// object1 := "object-name-1"// object2 := "object-name-2"// toObject := "object-name-3"ctx:=context.Background()client,err:=storage.NewClient(ctx)iferr!=nil{returnfmt.Errorf("storage.NewClient: %w",err)}deferclient.Close()ctx,cancel:=context.WithTimeout(ctx,time.Second*10)defercancel()src1:=client.Bucket(bucket).Object(object1)src2:=client.Bucket(bucket).Object(object2)dst:=client.Bucket(bucket).Object(toObject)// ComposerFrom takes varargs, so you can put as many objects here// as you want._,err=dst.ComposerFrom(src1,src2).Run(ctx)iferr!=nil{returnfmt.Errorf("ComposerFrom: %w",err)}fmt.Fprintf(w,"New composite object %v was created by combining %v and %v\n",toObject,object1,object2)returnnil}

Java

For more information, see theCloud StorageJava API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

importcom.google.cloud.storage.Blob;importcom.google.cloud.storage.BlobInfo;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;publicclassComposeObject{publicstaticvoidcomposeObject(StringbucketName,StringfirstObjectName,StringsecondObjectName,StringtargetObjectName,StringprojectId){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// The ID of the first GCS object to compose// String firstObjectName = "your-first-object-name";// The ID of the second GCS object to compose// String secondObjectName = "your-second-object-name";// The ID to give the new composite object// String targetObjectName = "new-composite-object-name";Storagestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();// Optional: set a generation-match precondition to avoid potential race// conditions and data corruptions. The request returns a 412 error if the// preconditions are not met.Storage.BlobTargetOptionprecondition;if(storage.get(bucketName,targetObjectName)==null){// For a target object that does not yet exist, set the DoesNotExist precondition.// This will cause the request to fail if the object is created before the request runs.precondition=Storage.BlobTargetOption.doesNotExist();}else{// If the destination already exists in your bucket, instead set a generation-match// precondition. This will cause the request to fail if the existing object's generation// changes before the request runs.precondition=Storage.BlobTargetOption.generationMatch(storage.get(bucketName,targetObjectName).getGeneration());}Storage.ComposeRequestcomposeRequest=Storage.ComposeRequest.newBuilder()// addSource takes varargs, so you can put as many objects here as you want, up to the// max of 32.addSource(firstObjectName,secondObjectName).setTarget(BlobInfo.newBuilder(bucketName,targetObjectName).build()).setTargetOptions(precondition).build();BlobcompositeObject=storage.compose(composeRequest);System.out.println("New composite object "+compositeObject.getName()+" was created by combining "+firstObjectName+" and "+secondObjectName);}}

Node.js

For more information, see theCloud StorageNode.js API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// The ID of the first GCS file to compose// const firstFileName = 'your-first-file-name';// The ID of the second GCS file to compose// const secondFileName = 'your-second-file-name';// The ID to give the new composite file// const destinationFileName = 'new-composite-file-name';// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctioncomposeFile(){constbucket=storage.bucket(bucketName);constsources=[firstFileName,secondFileName];// Optional:// Set a generation-match precondition to avoid potential race conditions// and data corruptions. The request to compose is aborted if the object's// generation number does not match your precondition. For a destination// object that does not yet exist, set the ifGenerationMatch precondition to 0// If the destination object already exists in your bucket, set instead a// generation-match precondition using its generation number.constcombineOptions={ifGenerationMatch:destinationGenerationMatchPrecondition,};awaitbucket.combine(sources,destinationFileName,combineOptions);console.log(`New composite file${destinationFileName} was created by combining${firstFileName} and${secondFileName}`);}composeFile().catch(console.error);

PHP

For more information, see theCloud StoragePHP API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

use Google\Cloud\Storage\StorageClient;/** * Compose two objects into a single target object. * * @param string $bucketName The name of your Cloud Storage bucket. *        (e.g. 'my-bucket') * @param string $firstObjectName The name of the first GCS object to compose. *        (e.g. 'my-object-1') * @param string $secondObjectName The name of the second GCS object to compose. *        (e.g. 'my-object-2') * @param string $targetObjectName The name of the object to be created. *        (e.g. 'composed-my-object-1-my-object-2') */function compose_file(string $bucketName, string $firstObjectName, string $secondObjectName, string $targetObjectName): void{    $storage = new StorageClient();    $bucket = $storage->bucket($bucketName);    // In this example, we are composing only two objects, but Cloud Storage supports    // composition of up to 32 objects.    $objectsToCompose = [$firstObjectName, $secondObjectName];    $targetObject = $bucket->compose($objectsToCompose, $targetObjectName, [        'destination' => [            'contentType' => 'application/octet-stream'        ]    ]);    if ($targetObject->exists()) {        printf(            'New composite object %s was created by combining %s and %s',            $targetObject->name(),            $firstObjectName,            $secondObjectName        );    }}

Python

For more information, see theCloud StoragePython API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

fromgoogle.cloudimportstoragedefcompose_file(bucket_name,first_blob_name,second_blob_name,destination_blob_name):"""Concatenate source blobs into destination blob."""# bucket_name = "your-bucket-name"# first_blob_name = "first-object-name"# second_blob_name = "second-blob-name"# destination_blob_name = "destination-object-name"storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)destination=bucket.blob(destination_blob_name)destination.content_type="text/plain"# Note sources is a list of Blob instances, up to the max of 32 instances per requestsources=[bucket.blob(first_blob_name),bucket.blob(second_blob_name)]# Optional: set a generation-match precondition to avoid potential race conditions# and data corruptions. The request to compose is aborted if the object's# generation number does not match your precondition. For a destination# object that does not yet exist, set the if_generation_match precondition to 0.# If the destination object already exists in your bucket, set instead a# generation-match precondition using its generation number.# There is also an `if_source_generation_match` parameter, which is not used in this example.destination_generation_match_precondition=0destination.compose(sources,if_generation_match=destination_generation_match_precondition)print("New composite object{} in the bucket{} was created by combining{} and{}".format(destination_blob_name,bucket_name,first_blob_name,second_blob_name))returndestination

Ruby

For more information, see theCloud StorageRuby API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.

defcompose_filebucket_name:,first_file_name:,second_file_name:,destination_file_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"# The ID of the first GCS object to compose# first_file_name = "your-first-file-name"# The ID of the second GCS object to compose# second_file_name = "your-second-file-name"# The ID to give the new composite object# destination_file_name = "new-composite-file-name"require"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_name,skip_lookup:truedestination=bucket.compose[first_file_name,second_file_name],destination_file_namedo|f|f.content_type="text/plain"endputs"Composed new file#{destination.name} in the bucket#{bucket_name} "\"by combining#{first_file_name} and#{second_file_name}"end

REST APIs

JSON API

  1. Have gcloud CLIinstalled and initialized, which lets you generate an access token for theAuthorization header.

  2. Create a JSON file that contains the following information:

    {"sourceObjects":[{"name":"SOURCE_OBJECT_1"},{"name":"SOURCE_OBJECT_2"}],"destination":{"contentType":"COMPOSITE_OBJECT_CONTENT_TYPE"}}

    Where:

  3. UsecURL to call theJSON API with aPOST Object request:

    curl -X POST --data-binary @JSON_FILE_NAME \  -H "Authorization: Bearer $(gcloud auth print-access-token)" \  -H "Content-Type: application/json" \  "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/COMPOSITE_OBJECT_NAME/compose"

    Where:

    • JSON_FILE_NAME is the name of the fileyou created in the previous step.
    • BUCKET_NAME is the name of the bucketthat contains the source objects.
    • COMPOSITE_OBJECT_NAME is the name you aregiving to the result of the object composition.

If successful, the response is anobject resource for theresulting composite object.

XML API

  1. Have gcloud CLIinstalled and initialized, which lets you generate an access token for theAuthorization header.

  2. Create an XML file that contains the following information:

    <ComposeRequest><Component><Name>SOURCE_OBJECT_1</Name></Component><Component><Name>SOURCE_OBJECT_2</Name></Component></ComposeRequest>

    Where:

    • SOURCE_OBJECT_1 andSOURCE_OBJECT_2 are the names of thesource objects to use in the object composition.
  3. UsecURL to call theXML API with aPUT Object request that includes thecompose query stringparameter:

    curl -X PUT --data-binary @XML_FILE_NAME \  -H "Authorization: Bearer $(gcloud auth print-access-token)" \  -H "Content-Type:COMPOSITE_OBJECT_CONTENT_TYPE" \  "https://storage.googleapis.com/BUCKET_NAME/COMPOSITE_OBJECT_NAME?compose"

    Where:

    • XML_FILE_NAME is the name of the file youcreated in the previous step.
    • COMPOSITE_OBJECT_CONTENT_TYPE is theContent-Type of the resulting composite object.
    • BUCKET_NAME is the name of the bucketthat contains the source objects.
    • COMPOSITE_OBJECT_NAME is the name you aregiving to the result of the object composition.

If successful, an empty response body is returned.

Note: The XML API supports including ageneration number for each<Component>, using either a<Generation> element or an<IfGenerationMatch> element.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.