【问题标题】:google app engine's ferris2.2 framework (python), uploading an image to cloud storage?google app engine ferris 2.2 framework (python),将图像上传到云存储?
【发布时间】:2015-10-05 15:57:50
【问题描述】:

所以.. 这是我上传带有 Ferris2 框架的图像的代码。是的,它有效。但是,看看我必须如何注释掉 gcs.open(... blobs。鉴于我坚持使用 AClassForm 和 ferris 框架,最简单的方法是什么?

class AClassForm(forms.model_form(AClass, exclude=('image_url') ) ):
     image = FileField(u'Image File') 

class AClasses(Controller): 

    class Meta: 

        Model = AClass 

        prefixes = ('admin',) 

        components = (scaffold.Scaffolding, Upload) 

        Form = AClassForm 



    admin_list = scaffold.list 

    admin_view = scaffold.view 

    admin_edit = scaffold.edit 

    admin_delete = scaffold.delete 



    def admin_add(self): 

        self.scaffold.ModelForm = AClassForm 

        self.scaffold.form_encoding = "multipart/form-data"    

        def before_save_callback(controller,container, item): 

            image = self.request.params["image"] 

            object_name = blobstore.parse_file_info(image).gs_object_name.split('/')[-1] 

            upload_settings = settings.get("upload") 

            url =  upload_settings["url"] 

            bucket = upload_settings["bucket"] 

            #send to the cloud 

            #write a task to execute this? 

            item.image_url  =  url % (bucket, object_name) 

            #gcs_file= gcs.open("/".join(["", bucket, object_name]),   

               # 'w', content_type="image/jpeg",  

                #options={'x-goog-acl': 'public-read'} )  

            #gcs_file.write(item.image)#.file.encode('utf-8')) # 

            #gcs_file.close() 

            return 

        self.events.scaffold_before_save += before_save_callback 

        return scaffold.add(self)

【问题讨论】:

    标签: google-app-engine google-cloud-storage blobstore image-upload


    【解决方案1】:

    我不确定 Ferris 在内部是如何工作的,但您可以直接使用 cloudstorage

    我的图像存储包装器,提供调整大小并返回上传的公共 URL,以便直接从存储中提供服务。

    import urlparse    
    from google.appengine.api import app_identity, blobstore, images
    import cloudstorage
    
    class ImageStorage(object):
    
        def __init__(self, base_uri):
            self.base_uri = "/{}/{}".format(app_identity.get_default_gcs_bucket_name(), base_uri.lstrip('/'))
    
        def put(self, image, name, mime=None, width=None, height=None):
            """Puts an image into the Google Cloud Storage"""
    
            if width or height:
                image = images.resize(image, width=width or height, height=height or width)
                mime = 'image/png'  # resize defaults to output_encoding=PNG
            options = {'x-goog-acl': 'public-read'}
            with cloudstorage.open(self.make_key(name), 'w', content_type=mime, options=options) as fp:
                fp.write(image)
            return self.get_url(name)
    
        def get_url(self, name):
            """Gets the url for an image from Google Cloud Storage"""
            key = self.make_key(name)
            # must be prefixed with /gs for the blob store to know it is from gcs
            # https://cloud.google.com/appengine/docs/python/blobstore/#Python_Using_the_Blobstore_API_with_Google_Cloud_Storage
            url = images.get_serving_url(blobstore.create_gs_key('/gs' + key))
    
            # s/https/http/ if running under dev_appserver.py
            # if not config.isLocal:
            #    parts = urlparse.urlparse(url)
            #    secure_parts = ('https',) + parts[1:]
            #    url = urlparse.urlunparse(secure_parts)
    
            return url
    
        def make_key(self, name):
            """Makes an item name key for Google Cloud Storage"""
            return '%s/%s' % (self.base_uri, name)
    

    webapp2.RequestHandler 的子类中使用。这会将名为“image”的文件存储在您的应用程序的默认存储桶中,路径为/some/bucket/path/my-image-name

    thumb = self.request.POST["image"]
    if hasattr(thumb, 'value'):
        gs_base_uri = '/some/bucket/path'
        image_storage = ImageStorage(gs_base_uri)
        thumb_fn = 'my-image-name'
        session_thumb_url = image_storage.put(image=thumb.value,
                                              name=thumb_fn,
                                              mime=thumb.type,
                                              width=300, height=300)
    
        return session_thumb_url
    

    【讨论】:

      【解决方案2】:

      据我了解,如果您使用的是 Ferris 的 Upload 组件,则无法逃脱 Blobstore,但以下内容非常接近。不想用Form类就不用了,我自己很少用。所以想象一下下面的控制器:

      from ferris import Controller, route
      from ferris.components.upload import Upload
      import cloudstorage as gcs
      from google.appengine.ext import blobstore
      import logging
      
      
      class ImageManager(Controller):
          class Meta:
              components = (Upload,)  
      
          @route
          def list(self):
              #This just passes the upload URL to use in the form
              self.context['upload_url'] = self.components.upload.generate_upload_url(uri=self.uri('image_manager:image_uploader_action'))
      
      
          @route
          def image_uploader_action(self):
              # This gets all of the uploads passed in from the form
              uploads = self.components.upload.get_uploads()
      
              # This is the raw google cloud object reference. 'myfile' is the name of the upload field in the html form
              file_gcs_obj_name = uploads['myfile'][0].cloud_storage.gs_object_name 
      
              # This is the blobstore key just for giggles
              file_blobstore_key = uploads['myfile'][0].key()
      
              # This will get rid of the preceeding junk you don't need i.e. "/gs/yadda/yadda"
              clean_file_name = file_gcs_obj_name[3:]
      
              # This is the name of the file as it was uploaded by the end-user
              file_name_friendly  = uploads['myfile'][0].filename
      
              # This is the actual file, with this you can do whatever you want
              the_actual_image = gcs.open(clean_file_name,'r')
      
              # The file name by default is long and ugly, lets make a copy of the file with a more friendly name
              new_filename = '/mydomain.appspot.com/'+file_name_friendly
              gcs.copy2(clean_file_name,new_filename)
      
              # We can generate a serving URL by using the blobstore API
              valid_blob_reference = blobstore.create_gs_key('/gs'+new_filename)
              file_serving_url = images.get_serving_url(valid_blob_reference)
              logging.info('the serving url is: %s'% file_serving_url)
      
              # delete the original image from cloud storage
              gcs.delete(clean_file_name)
      
              # Delete the original image from blobstore
              blobstore.delete(file_blobstore_key)
      
              # Close the file
              the_actual_image.close()
      
              return 'Done. go check the cloud storage browser'
      

      现在您只需要 HTML 表单。你可以使用这样的东西:

      {% extends "layouts/default.html" %}
      {% block layout_content %}
      <form name="myform" action="{{upload_url}}" method="POST" enctype="multipart/form-data">
          <input type="file" name="myfile" id="fileToUpload">
          <input type="submit" value="Upload File" name="submit">
      </form>
      {% endblock %}
      

      Ferris 仍会在 blobstore 中放置一个文件,但您可以在使用 cloudstorage.copy2() 函数后将其删除。该功能相当新,因此请记得更新您的云存储包,您可以从 Google 或 Pypi (https://pypi.python.org/pypi/GoogleAppEngineCloudStorageClient/1.9.22.1) 下载最新副本 希望这会有所帮助。

      【讨论】:

      • 好像你做了 gcs.open,但你从来没有写过图像,意思是 gcs.write(?)。那是故意的吗?你知道这段代码是否有效吗?
      • 您说得对,在我的示例中完全不需要打开,因为 Upload 组件已经将其放入 cloudstore。唯一缺少的是生成一个服务 URL(我更新了)今天确实有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-04
      • 2015-08-12
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      相关资源
      最近更新 更多