Using Google Cloud Storage
Google Cloud Storage is a managed service for storing unstructured data.
The Rust client library provides an idiomatic API to access this service. The client library resumes interrupted downloads and uploads, and automatically performs integrity checks on the data. For metadata operations, the client library can retry failed requests, and automatically poll long-running operations.
Quickstart
This guide will show you how to create a Cloud Storage bucket, upload an object to this bucket, and then read the object back.
Prerequisites
The guide assumes you have an existing Google Cloud project with billing enabled.
Add the client library as a dependency
cargo add google-cloud-storage
Create a storage bucket
The client to perform operations on buckets and object metadata is called
StorageControl
:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
To create a bucket you must provide the project name and the desired bucket id:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
You can also provide other attributes for the bucket. For example, if you want all objects in the bucket to use the same permissions, you can enable Uniform bucket-level access:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
Then send this request and wait for the response:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
Upload an object
The client to perform operations on object data is called Storage
:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
In this case we will create an object called hello.txt
, with the traditional
greeting for a programming tutorial:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
Download an object
To download the contents of an object use read_object()
:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
Cleanup
Finally we remove the object and bucket to cleanup all the resources used in this guide:
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}
Next Steps
Full program
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub async fn quickstart(project_id: &str, bucket_id: &str) -> anyhow::Result<()> {
use google_cloud_storage as gcs;
use google_cloud_storage::client::StorageControl;
let control = StorageControl::builder().build().await?;
let bucket = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(bucket_id)
.set_bucket(
gcs::model::Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_iam_config(
gcs::model::bucket::IamConfig::new().set_uniform_bucket_level_access(
gcs::model::bucket::iam_config::UniformBucketLevelAccess::new()
.set_enabled(true),
),
),
)
.send()
.await?;
println!("bucket successfully created {bucket:?}");
use google_cloud_storage::client::Storage;
let client = Storage::builder().build().await?;
let object = client
.write_object(&bucket.name, "hello.txt", "Hello World!")
.send_buffered()
.await?;
println!("object successfully uploaded {object:?}");
let mut reader = client.read_object(&bucket.name, "hello.txt").send().await?;
let mut contents = Vec::new();
while let Some(chunk) = reader.next().await.transpose()? {
contents.extend_from_slice(&chunk);
}
println!(
"object contents successfully downloaded {:?}",
bytes::Bytes::from_owner(contents)
);
control
.delete_object()
.set_bucket(&bucket.name)
.set_object(&object.name)
.set_generation(object.generation)
.send()
.await?;
control
.delete_bucket()
.set_name(&bucket.name)
.send()
.await?;
Ok(())
}