使用Google App Engine图像的明确示例get_serving_url()

时间:2011-07-04 00:26:58

标签: google-app-engine image-processing google-cloud-platform blobstore

有人知道这个例子吗?我无法在Google的文档中找到一个。

4 个答案:

答案 0 :(得分:7)

尽管有文档,I was pretty confused也有一段时间了。

现在我更了解它(我想!),我会提供一个例子。

get_serving_url()位于google.appengine.ext.blobstore班级,takes one positional argument位于BlobKey

BlobKey可以用字符串构建:blobstore.BlobKey('this is the key')

因此,这为我们提供了get_serving_url()的基本实现所需的一切:

from google.appengine.ext.blobstore import BlobKey
from google.appengine.api.images import get_serving_url

key = BlobKey('imagekey')
url = get_serving_url(key)

到目前为止一切都很精致。

该函数还需要三个关键字参数as documented。这些是sizecropsecure_urlrpc

  • secure_url = True只返回https个网址,而不是http(默认为False
  • rpc是异步处理的某些设置的RPC对象。我不太了解它,或者确实自己使用它!
  • crop = True以均匀的比例裁剪图像正方形。

size一开始让我很困惑。 本身不会生成不同的网址。唯一的区别在于后缀=sXX,您可以自由设置。

就个人而言,我将原始尺寸网址存储在我的db.Model中,然后在任何地方使用imgUrl+'=s150'(例如)。没有必要为您需要的每个不同大小调用get_serving_url(),没有性能损失,因为它完全相同。

另请注意,指定的尺寸是图像的最大尺寸。这很奇怪地隐藏在文档中 - 我认为它必须是宽度一段时间,但如果图像是“肖像”,当然它是高度。

您还可以附加-c(相当于crop=True)。

所以,为了我们更完整(虽然我缺乏证明使用RPC对象的知识)示例:

from google.appengine.ext.blobstore import BlobKey
from google.appengine.api.images import get_serving_url
from webapp2 import RequestHandler

class sample(RequestHandler):

    def get(self):
        key = BlobKey('imagekey')
        url = get_serving_url(key, secure_url=True)

        #get_serving_url(key, secure_url=True, size=150, crop=True)
        urlThumb = url + '=s150-c'

        #get_serving_url(key, secure_url=True, size=50)
        urlMini  = url + '=s50'

        self.response.write('Here is my thumbnail: <img src="%s"><br>'%urlThumb)
        self.response.write('Here is mini-me!: <img src="%s"><br>'%urlMini)
        self.response.write('And back to full-size: <img src="%s"><br>'%url)

然后,可以将这些URL存储在数据存储区中与它们相关的任何模型中。这比使用完全不同的 db.BlobProperty更受欢迎,这根本不适用于图像。它也更昂贵,效率更低。

当然,我建议你只存储url(如上所述),因为通过后缀字符串来改变大小非常容易!事实上,你可以在你的Jinja模板(或等效的)中真正做到这一点 - 否则你可能会指定width=并通过在CSS中执行相同的操作来裁剪。

答案 1 :(得分:4)

get_serving_url已记录在案here。这里没有端到端的例子,但它非常简单:你传递一个blob键,以及可选的调整大小和裁剪选项,它会返回一个URL。您可以在任何想要引用图像的地方使用该URL,它将由基础结构提供,调整大小并适当裁剪。

请注意,这仅适用于上传到blobstore的图像。任何上传到常规数据存储区并存储在BlobProperty中的内容都必须自行调整大小,裁剪和投放。

答案 2 :(得分:1)

我一直使用以下代码上传图片,然后使用CDN提供图像。请参阅代码中的注释以获得解释。

import webapp2
from google.appengine.api import users
import os
import jinja2
from models import Note
from models import NoteFile
from models import CheckListItem
from google.appengine.ext import ndb
from google.appengine.api import app_identity
from google.appengine.api import images
from google.appengine.ext import blobstore
import lib.cloudstorage as cloudstorage
import mimetypes

jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))

#Request Handler
class MainHandler(webapp2.RequestHandler):  
    #Post Method for uploading images  
    def post(self):
        #Gets the currently logged in user
        user = users.get_current_user() 
        if user is None:
            self.error(401)
        #Gets Default Bucket for Google Cloud Storage. This is where uploaded image will be saved
        bucket_name = app_identity.get_default_gcs_bucket_name()
        uploaded_file = self.request.POST.get('uploaded_file')
        file_name = getattr(uploaded_file, 'filename', None)
        file_content = getattr(uploaded_file, 'file', None)
        real_path = ''

        if file_name and file_content:
            content_t = mimetypes.guess_type(file_name)[0]
            real_path = os.path.join('/', bucket_name, user.user_id(), file_name)
            #Read file from the uploaded stream and write to the cloud storage bucket
            with cloudstorage.open(real_path, 'w', content_type=content_t) as f:
                f.write(file_content.read())
        else:
            print 'File can not be written'
        #This will save the NDB models
        self._create_note(user, file_name, real_path)

        logout_url = users.create_logout_url(self.request.uri)
        template_context = {
            'user': user.nickname(),
            'logout_url': logout_url
        }
        #Response with the data
        self.response.write(self._render_template('main.html', template_context))

    #Makes the method atomic
    @ndb.transactional
    def _create_note(self, user, file_name, file_path):
        note = Note(parent=ndb.Key("User", user.nickname()),
                    title=self.request.get('title'),
                    content=self.request.get('content'))
        note.put()

        if file_name and file_path:
            url, thumbnail_url = self._get_urls_for(file_name)
            f = NoteFile(parent=note.key, name=file_name, url=url, thumbnail_url=thumbnail_url, full_path=file_path)
            f.put()
            note.files.append(f.key)
        note.put()

    def _render_template(self, template_name, context=None):
        if context is None:
            context = {}
        user = users.get_current_user()
        ancestor_key = ndb.Key("User", user.nickname())
        qry = Note.owner_query(ancestor_key)
        context['notes'] = qry.fetch()
        template = jinja_env.get_template(template_name)
        return template.render(context)

    def _get_urls_for(self, file_name):
        user = users.get_current_user()
        if user is None:
            return
        #Gets Default Bucket
        bucket_name = app_identity.get_default_gcs_bucket_name()
        path = os.path.join('/', bucket_name, user.user_id(), file_name)
        #This is required to generate the blobstore key
        real_path = '/gs' + path
        key = blobstore.create_gs_key(real_path)
        #This is going to generate url for original sized image
        url = images.get_serving_url(key, size=0)
        #Generates url for cropped and 150px max dimension image. The image will be uploaded once, but will dynamically be transformed acc to parameters provided
        thumbnail_url = images.get_serving_url(key, size=150, crop=True)
        return url, thumbnail_url


app = webapp2.WSGIApplication([
    (r'/', MainHandler)
], debug=True)

这是模型类

class Note(ndb.Model):
    title = ndb.StringProperty()
    content = ndb.TextProperty()
    date_created = ndb.DateTimeProperty(auto_now_add=True)
    files = ndb.KeyProperty("NoteFile",repeated=True)

    @classmethod
    def owner_query(cls, parent_key):
        return cls.query(ancestor=parent_key).order(-cls.date_created)


class NoteFile(ndb.Model):
    name = ndb.StringProperty()
    url = ndb.StringProperty()
    thumbnail_url = ndb.StringProperty()
    full_path = ndb.StringProperty()

如果有什么不清楚,请告诉我。

答案 3 :(得分:0)

我也非常困惑,因为谷歌并没有真正为JAVA程序员提供getServingUrl()的工作示例 - Ollie,我认为上面给出的示例代码是用Python编写的?

我做了一些编码,看看它是如何工作的,这是java中一个有效的代码片段(人们可以轻松地从google的网站上找到工作示例:https://cloud.google.com/appengine/docs/java/blobstore/并用这个替换在Serve.java下编写的代码一段代码):

   @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws IOException {
            BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));

            ImagesService imagesService = ImagesServiceFactory.getImagesService();

            String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(blobKey).crop(true).imageSize(200));
            PrintWriter out = res.getWriter();
            out.println("Here is my thumbnail! <img src="+ url + ">");

        }
}

这会将您发布的图像发布到blobstore,裁剪它,使其成为一个宽200高的漂亮正方形,然后以HTML格式打印出来,以便您可以看到缩略图。

希望这有助于那里的人!