【问题标题】:How to upload an image to Google Cloud Storage from App Engine如何从 App Engine 将图像上传到 Google Cloud Storage
【发布时间】:2021-07-07 15:00:26
【问题描述】:

我正在尝试获取 base64 编码的 PNG,对其进行解码,然后将其上传到 Google Cloud Storage 并获取其公共 URL。

我可以通过将 PNG 保存到文件然后使用 blob.upload_from_file('picture.png') 上传它来在本地执行此操作,但 App Engine 不允许对其文件结构进行写访问。

此代码在本地有效,但在 Google App Engine 中无效,在 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

GCS 文档告诉Use the Blob.upload_from_file(), Blob.upload_from_filename(), or Blob.upload_from_string() method to upload an object.

但是,这些方法都不适用于这种情况,因为没有文件,只有一个编码的 PNG 对象。如何将其上传到 gcloud 存储?

我肯定遗漏了一些明显的东西。任何想法将不胜感激。

【问题讨论】:

  • 如果您使用的是 AppEngine,则不需要使用特定的身份验证详细信息。您可以通过设置GOOGLE_APPLICATION_CREDENTIALS 环境变量在本地复制它。确保您已授予 AppEngine 使用其他 Google 服务的正确权限,因为默认情况下这些服务被拒绝。您可以在控制台中执行此操作。并查看NamedTemporaryFile 以正确支持多个并发请求。
  • 临时文件夹正是我所需要的。
  • 大卫的建议是完美的。我只需要临时存储空间。
  • @David 你能把你的评论变成答案吗?帮助他人

标签: python django google-app-engine google-cloud-storage


【解决方案1】:

根据 David 的建议,这是行之有效的。我只是在文件名之前添加了/tmp/,App Engine 允许我保存它。

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

【讨论】:

    【解决方案2】:
    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);
    

    【讨论】:

    • 上次我忘记添加credentials.json ......因为我是从另一部分调用它的。谢谢@ian-campbell 的编辑建议跨度>
    最近更新 更多