Google Cloud Storage ist der Objektspeicherdienst von Google. Daten liegen in Buckets, und jeder Bucket enthält Objekte (Dateien), die Sie hochladen, auflisten, lesen und löschen. Der meiste Delphi-Code erreicht ihn über die JSON-REST-API, aber der Storage-Dienst stellt auch eine gRPC-API bereit, die Protocol Buffers über HTTP/2 spricht. sgcWebSockets Enterprise liefert einen typisierten Cloud-Storage-gRPC-Client auf Basis von TsgcGRPCClient, sodass Sie Buckets und Objekte aus Delphi und C++Builder steuern können, ohne externe Laufzeitumgebung oder generierte Stubs.
Wie es funktioniert
Die gRPC-Storage-API befindet sich unter storage.googleapis.com:443 und spricht den Dienst google.storage.v2.Storage. sgcWebSockets liefert bereits einen vollständigen HTTP/2-Stack, sodass der typisierte Client auf einem TsgcHTTP2Client-Transport mit aktiviertem TLS aufsetzt. TsgcGRPCClient übernimmt das gRPC-Framing, die Header und die Timeout-Behandlung, öffnet den HTTP/2-Stream und parst die Response und die Trailer zurück in ein TsgcGRPCResponse.
Die typisierte Schicht befindet sich in der Unit sgcGRPC_Google_Storage. Sie gibt Ihnen Request- und Response-Klassen wie TsgcGRPCStorageListBucketsRequest, TsgcGRPCStorageListObjectsResponse und TsgcGRPCStorageBucket, die sich selbst zu und von Protocol Buffers serialisieren. Sie setzen typisierte Eigenschaften, rufen ToBytes auf, um die Request-Nutzdaten zu erhalten, senden sie mit Call und laden die Antwort mit LoadFromBytes. Kein Protobuf-Compiler, keine handgeschriebenen Feld-Tags.
Die Authentifizierung verwendet ein Google-Dienstkonto. Der Client signiert einen JSON Web Token aus dem Dienstkonto-Schlüssel und präsentiert ihn als Bearer-Token in den gRPC-authorization-Metadaten, was die standardmäßige Art ist, wie Google Cloud Server-zu-Server-Aufrufe autorisiert.
Den Transport einrichten
Ein gRPC-Channel ist einfach eine HTTP/2-Verbindung. Richten Sie einen TsgcHTTP2Client mit aktiviertem TLS auf den Storage-Endpunkt, hängen Sie ihn dann an TsgcGRPCClient an und wählen Sie den binären Protocol-Buffers-Content-Type.
uses
sgcHTTP2_Client, sgcGRPC_Client, sgcGRPC_Types, sgcGRPC_Google_Storage;
var
HTTP2: TsgcHTTP2Client;
GRPC: TsgcGRPCClient;
begin
HTTP2 := TsgcHTTP2Client.Create(nil);
HTTP2.Host := 'storage.googleapis.com';
HTTP2.Port := 443;
HTTP2.TLS := True;
GRPC := TsgcGRPCClient.Create(nil);
GRPC.Client := HTTP2;
GRPC.ChannelOptions.ContentType := grpcProto;
GRPC.ChannelOptions.Compression := grpcNoCompression;
HTTP2.Active := True;
end;
Authentifizierung mit einem Dienstkonto
Laden Sie den Dienstkonto-JSON-Schlüssel, konfigurieren Sie ein für den Storage-Endpunkt signiertes JWT und legen Sie das resultierende Token in DefaultMetadata ab, sodass es bei jedem Aufruf mitgesendet wird. Das selbstsignierte Dienstkonto-JWT ist audience-gebunden, daher muss API_Endpoint auf storage.googleapis.com verweisen, damit das Token akzeptiert wird.
var
Cloud: TsgcHTTPGoogleCloud_PubSub_Client;
begin
Cloud := TsgcHTTPGoogleCloud_PubSub_Client.Create(nil);
Cloud.LoadSettingsFromFile('service-account.json');
Cloud.GoogleCloudOptions.Authentication := gcaJWT;
Cloud.GoogleCloudOptions.JWT.API_Endpoint := 'https://storage.googleapis.com/';
// OnAuthToken fires when the token is ready; copy it into the gRPC metadata
GRPC.DefaultMetadata.Clear;
GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);
end;
Buckets auflisten
Um die Buckets in einem Projekt aufzuzählen, füllen Sie einen TsgcGRPCStorageListBucketsRequest mit dem Projekt als Parent, serialisieren ihn und führen einen unären Call zur Methode ListBuckets aus. Die Antwort-Bytes laden direkt in ein TsgcGRPCStorageListBucketsResponse, das jeden Bucket mit seinem Namen und Standort bereitstellt.
var
oRequest: TsgcGRPCStorageListBucketsRequest;
oResponse: TsgcGRPCResponse;
oBuckets: TsgcGRPCStorageListBucketsResponse;
i: Integer;
begin
oRequest := TsgcGRPCStorageListBucketsRequest.Create;
try
oRequest.Parent := 'projects/' + ProjectId;
oRequest.PageSize := 100;
oResponse := GRPC.Call('google.storage.v2.Storage', 'ListBuckets',
oRequest.ToBytes);
finally
oRequest.Free;
end;
if oResponse.StatusCode = grpcOK then
begin
oBuckets := TsgcGRPCStorageListBucketsResponse.Create;
try
oBuckets.LoadFromBytes(oResponse.Data);
for i := 0 to oBuckets.BucketCount - 1 do
Memo1.Lines.Add(oBuckets.Bucket(i).Name + ' (location: ' +
oBuckets.Bucket(i).Location + ')');
finally
oBuckets.Free;
end;
end;
end;
Einen Bucket erstellen
Das Erstellen eines Buckets folgt demselben Muster mit TsgcGRPCStorageCreateBucketRequest. Setzen Sie das Parent-Projekt, die neue Bucket-ID und das Projekt, dem die Bucket-Ressource gehört, und rufen Sie dann CreateBucket auf. Die Response trägt den erstellten TsgcGRPCStorageBucket.
var
oRequest: TsgcGRPCStorageCreateBucketRequest;
oResponse: TsgcGRPCResponse;
begin
oRequest := TsgcGRPCStorageCreateBucketRequest.Create;
try
oRequest.Parent := 'projects/' + ProjectId;
oRequest.BucketId := 'my-new-bucket';
oRequest.Bucket.Project := 'projects/' + ProjectId;
oResponse := GRPC.Call('google.storage.v2.Storage', 'CreateBucket',
oRequest.ToBytes);
finally
oRequest.Free;
end;
end;
Objekte in einem Bucket auflisten
Das Auflisten der Objekte in einem Bucket verwendet TsgcGRPCStorageListObjectsRequest. Der Parent ist der Bucket-Ressourcenname in der Form projects/_/buckets/<bucket>. Die Response gibt Ihnen den Namen, die Größe und den Content-Type jedes Objekts, und Sie können optional Prefix und Delimiter setzen, um eine ordnerartige Hierarchie zu durchlaufen.
var
oRequest: TsgcGRPCStorageListObjectsRequest;
oResponse: TsgcGRPCResponse;
oObjects: TsgcGRPCStorageListObjectsResponse;
i: Integer;
begin
oRequest := TsgcGRPCStorageListObjectsRequest.Create;
try
oRequest.Parent := 'projects/_/buckets/' + BucketName;
oRequest.PageSize := 100;
oResponse := GRPC.Call('google.storage.v2.Storage', 'ListObjects',
oRequest.ToBytes);
finally
oRequest.Free;
end;
if oResponse.StatusCode = grpcOK then
begin
oObjects := TsgcGRPCStorageListObjectsResponse.Create;
try
oObjects.LoadFromBytes(oResponse.Data);
for i := 0 to oObjects.ObjectCount - 1 do
Memo1.Lines.Add(oObjects.Object_(i).Name + ' (size: ' +
IntToStr(oObjects.Object_(i).Size) + ', type: ' +
oObjects.Object_(i).ContentType + ')');
finally
oObjects.Free;
end;
end;
end;
Objektdaten lesen und schreiben
Über die Bucket- und Objekt-Metadaten hinaus deckt die Unit auch Objekt-Nutzdaten ab. TsgcGRPCStorageReadObjectRequest liest Bytes aus einem Objekt zurück, mit optionalem ReadOffset und ReadLimit für bereichsbezogene Downloads, und die passende Response stellt die rohen Data-Bytes bereit. TsgcGRPCStorageWriteObjectRequest lädt Objektinhalt in Chunks hoch: Setzen Sie die WriteObjectSpec-Ressource für den ersten Chunk, schieben Sie Data bei steigenden WriteOffset-Werten und markieren Sie FinishWrite beim letzten Chunk. Da jede Nachricht über ToBytes und LoadFromBytes serialisiert wird, funktionieren dieselben typisierten Klassen, egal ob Sie eine kleine Datei in einem Aufruf hochladen oder ein großes Objekt in Teilen streamen.
Pagination und Fehlerbehandlung
Die Listen-Responses geben einen NextPageToken zurück, wenn weitere Ergebnisse verfügbar sind. Kopieren Sie ihn in das PageToken des nächsten Requests und rufen Sie erneut auf, um durch große Buckets oder lange Objektlisten zu blättern. Auf der Fehlerseite trägt jedes TsgcGRPCResponse einen typisierten StatusCode, sodass ein Nicht-grpcOK-Ergebnis Ihnen genau sagt, was schiefgelaufen ist, von grpcUNAUTHENTICATED für ein fehlerhaftes oder fehlendes Token bis grpcNOT_FOUND für einen fehlenden Bucket. Für asynchrone Arbeit liefern OnGRPCResponse, OnGRPCError und OnGRPCException dieselben Informationen über Ereignisse.
Verfügbarkeit
Der typisierte Google-Cloud-Storage-gRPC-Client ist Teil der sgcWebSockets Enterprise Edition. Ein vollständiges, sofort lauffähiges Beispiel befindet sich in Demos\21.GRPC\15.Cloud_Storage und deckt Authentifizierung, Auflisten und Erstellen von Buckets sowie Auflisten von Objekten ab. Die vollständige Referenz finden Sie auf der gRPC-Client-Produktseite.
Fragen oder Feedback? Nehmen Sie Kontakt auf. Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.
