How to directly send file to client from google storage in python?

1.7k views Asked by At

I want to send any file to client on request, from google storage , but its downloading locally on server. I don't to download locally rather if any way I can send file to client directly.

Currently I am doing this way for download

def download_file(self, bucket, key, path_to_download):
        bucket = gc_storage.storage_client.bucket(bucket)
        blob = bucket.blob(key)
        blob.download_to_filename(path_to_download)

1

There are 1 answers

1
Paddy Alton On

I don't think there is an API method to load data from GCS to a generic third location, although some data transfer options exist for certain specific use cases.

As mentioned in the comments, smart-open could be an option here, provided you're willing to at least stream the data through your server. Perhaps something like this:

from dotenv import load_dotenv
from google.cloud.storage import Client
from os import getenv
from smart_open import open


# load environment variables from a file
load_dotenv("<path/to/.env")

# get the path to a service account credentials file from an environment variable
service_account_path = getenv("GOOGLE_APPLICATION_CREDENTIALS")

# create a client using the service account credentials for authentication
gcs_client = Client.from_service_account_json(service_account_path)

# use this client to authenticate your transfer
transport = {"client": gcs_client}


with open("gs://my_bucket/my_file.txt", transport_params=transport) as f_in:
    with open("gs://other_bucket/my_file.txt", "wb", transport_params=transport) as f_out:
        for line in f_in:
            f_out.write(line)

Here I've written out the full machinery for doing this with a service account, on the assumption that you aren't authenticated by default. My understanding is that you may be able to remove most of that if your computer is already set up to connect to GCS with some default credentials:

from smart_open import open

with open("gs://my_bucket/my_file.txt") as f_in:
    with open("gs://other_bucket/my_file.txt", "wb") as f_out:
        for line in f_in:
            f_out.write(line)

Note also that I've written this as if you were transferring the file from one GCS bucket to another one - but this is actually one of those cases where there is a built-in API method to achieve the goal!

# ... [obtain gcs_client as before] ...

my_bucket = gcs_client.get_bucket("my-bucket")
other_bucket = gcs_client.get_bucket("other-bucket")

my_file = my_bucket.get_blob("my-file.txt")

my_bucket.copy_blob(my_file, other_bucket)

It sounds like what you actually want to do is pass on the data to a third party, so the inner with statement will need replacing with whatever implementation you are actually using.