谷歌应用引擎的ferris2.2框架(python),将图像上传到云存储?

时间:2015-10-05 15:57:51

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

所以..这是我使用Ferris2框架工作上传图像的代码。是的,它有效。但是,看看我如何评论gcs.open(...?我不想要注释掉。我真的很想直接上传到使用该电话的云存储,而不是必须使用与blob相关的任何东西。考虑到我使用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)

2 个答案:

答案 0 :(得分:0)

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

function CheckTextChange() {

    //Checks if values have changed in elements containing class="txt" 
    var isChanged = false;
    $('.txt').each(function () {
        var previousVal = $(this).get(0).defaultValue,
            currentVal = $(this).val();
        //alert( $(this).text()); //or $(this).text();

        if (currentVal != previousVal) {
            isChanged = true;
        }
    });

    return isChanged;
}

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

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'

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

答案 1 :(得分:0)

我不确定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