Reputation: 1665
I'm trying to take a base64-encoded PNG, decode it, then upload it to Google Cloud Storage and get its public URL.
I can do it locally by saving the PNG to file and then uploading it with blob.upload_from_file('picture.png')
, but App Engine doesn't allow write access to its file structure.
This code works locally but not in Google App Engine, where it fails at with open(...
import base64
from google.cloud import storage
def handler(request):
pic = request.POST.get('photograph') #Object like 'data:image/png;base64,iVBORw0KGgoAAAAN…'
data = pic[22:]
png = base64.b64decode(data)
filename = "pic.png"
with open(filename, "wb") as f:
f.write(png)
client = storage.Client.from_service_account_json(os.path.abspath('credentials.json'))
bucket = client.get_bucket('mybucket')
blob = bucket.blob(filename) #create destination uri in bucket
blob.upload_from_file(filename)
image_url = "https://storage.googleapis.com/mybucket/" + filename
The GCS docs say to Use the Blob.upload_from_file(), Blob.upload_from_filename(), or Blob.upload_from_string() method to upload an object.
However none of those methods work for this situation because there is no file, just an encoded PNG object. How can I upload it to gcloud storage?
I'm surely missing something obvious. Any ideas would be much appreciated.
Upvotes: 1
Views: 2874
Reputation: 537
import base64
from google.cloud import storage
#The post_image_base64 is base64 string
base64_img_bytes = post_image_base64.encode('utf-8')
#this for localhost if you want to upload it to gcloud storage then you have to add this path /tmp/
"""
with open('/tmp/'+'decoded_image.png', 'wb') as file_to_save:
decoded_image_data = base64.decodebytes(base64_img_bytes)
"""
with open('decoded_image.png', 'wb') as file_to_save:
decoded_image_data = base64.decodebytes(base64_img_bytes)
##Save file
#file_to_save.write(decoded_image_data)
gcs=storage.Client.from_service_account_json(os.path.abspath('credentials.json'))
bucket = gcs.get_bucket("bucket_name")
blob = bucket.blob("image_name.png")
#for upload to gcloud storage you also need to add /tmp/ path in here
#blob.upload_from_string("/tmp/"+decoded_image_data)
blob.upload_from_string(decoded_image_data)
#and then make it public use this
blob = bucket.get_blob('image_name.png')
blob_url = blob.make_public()
print(blob.public_url);
Upvotes: 1
Reputation: 1665
As per David's suggestion, this is what worked. I simply added /tmp/
before the filename and App Engine allowed me to save it.
import base64
from google.cloud import storage
def handler(request):
pic = request.POST.get('photograph')
data = pic[22:]
png = base64.b64decode(data)
filename = "pic.png"
temp_location = '/tmp/' + filename #here
with open(temp_location, "wb") as f:
f.write(png)
client = storage.Client.from_service_account_json(os.path.abspath('credentials.json'))
bucket = client.get_bucket('mybucket')
blob = bucket.blob(filename)
blob.upload_from_file(temp_location)
image_url = "https://storage.googleapis.com/mybucket/" + filename
Upvotes: 4