> For the complete documentation index, see [llms.txt](https://docs.flexbase.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flexbase.in/data-and-providers/data-stores/file-store/gcp-cloud-storage-google.md).

# Gcp Cloud Storage (Google)

## Description

Google Cloud Storage can be used as the backing implementation for Flex file operations. Your application code should depend on `IFlexFileStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexFileStore` is the contract**: your code uploads/downloads through a shared abstraction.
* **Streaming**: uploads use a `Stream`; downloads return a `Stream?`.
* **Credentials**: prefer service accounts; keep credentials out of source control.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers GCP Cloud Storage as the IFlexFileStore bridge.
		services.AddFlexGcpCloudStorageFileStore(configuration);
		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:File:GcpCloudStorage`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "File": {
		"GcpCloudStorage": {
		  "ProjectId": "your-gcp-project-id",
		  "BucketName": "your-bucket-name",
		  "CredentialsJsonPath": "C:/secrets/gcp-service-account.json"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Upload file (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Files;

public partial class UploadFileHandler : IAmFlexCommandHandler<UploadFileCommand>
{
	protected string EventCondition = "";
	protected readonly ILogger<UploadFileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;

	public UploadFileHandler(ILogger<UploadFileHandler> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual async Task Execute(UploadFileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		var appContext = cmd.Dto.GetAppContext(); // do not remove this line
		var model = _flexHost.GetDomainModel<FileModel>().Create(cmd);

		var fileId = await _fileStore.UploadAsync(cmd.Dto.Stream, cmd.Dto.FileName, cmd.Dto.ContentType, cmd.Dto.Metadata);
		await this.Fire(EventCondition, serviceBusContext);
	}
}

public class UploadFileCommand : FlexCommandBridge<UploadFileDto> { }
public class UploadFileDto : DtoBridge
{
	public Stream Stream { get; set; }
	public string FileName { get; set; }
	public string ContentType { get; set; }
	public IDictionary<string, string>? Metadata { get; set; }
}
public class FileModel : FlexDomainModelBridge { }
```

### Download file (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Files;

public class DownloadFileQuery : FlexiQueryBridgeAsync<FileDownloadOutput>
{
	protected readonly IFlexFileStore _fileStore;
	protected DownloadFileParams _params;

	public DownloadFileQuery(ILogger<DownloadFileQuery> logger, IFlexHost flexHost, IFlexFileStore fileStore)
		=> _fileStore = fileStore;

	public virtual DownloadFileQuery AssignParameters(DownloadFileParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<FileDownloadOutput?> Fetch()
	{
		var appContext = _params.GetAppContext();
		var stream = await _fileStore.DownloadAsync(_params.FileId);
		if (stream == null) return default;
		return new FileDownloadOutput { FileId = _params.FileId, Stream = stream };
	}
}

public class DownloadFileParams : DtoBridge { public string FileId { get; set; } }
public class FileDownloadOutput : DtoBridge { public string FileId { get; set; } public Stream Stream { get; set; } }
```

## Library-specific considerations

* **Service account permissions**: grant `storage.objects.create`, `storage.objects.get`, and `storage.objects.list` on the bucket.
* **Credentials path**: prefer mounting the JSON file at runtime (or use workload identity where available).
