将 blobstore 与谷歌云端点和 android 一起使用 [英] using blobstore with google cloud endpoint and android

查看:24
本文介绍了将 blobstore 与谷歌云端点和 android 一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 eclipse 插件开发一个应用引擎连接的 android 项目.该应用程序的一个方面是允许用户 Alpha 向用户 Bravo 发送图片.为此,我进行了以下设置:

I am developing an app-engine connected android project using the eclipse plugin. One aspect of the app is to allow user Alpha to send pictures to user Bravo. To do that I have the following setup:

用户 Alpha 发布:

User Alpha posting:

  • 通过端点将图像发送到我的应用引擎服务器
  • 服务器将图像存储在 blob 存储中
  • 服务器将 blobkey 存储在数据存储区

用户 Bravo 获得:

User Bravo getting:

  • 服务器从数据存储区获取 blobkey
  • 服务器使用 blob 键获取图像
  • 服务器使用端点将图像发送到安卓应用

从我的 android 应用程序发送图像到我可以在 blob 疮中看到它,此设置需要两 (2) 分钟以上的时间.不用说,这是完全不能接受的.

This setup takes upward of two (2) minutes from when my android app sends an image to when I can see it in the blob sore. Needless to say this is completely unacceptable.

我的服务器正在通过以下代码以编程方式处理图像:

My server is processing the image programmatically, thru the following code:

public static BlobKey toBlobstore(Blob imageData) throws FileNotFoundException, FinalizationException, LockException, IOException {
        if (null == imageData)
            return null;

        // Get a file service
        FileService fileService = FileServiceFactory.getFileService();

        // Create a new Blob file with mime-type "image/png"
        AppEngineFile file = fileService.createNewBlobFile("image/jpeg");// png

        // Open a channel to write to it
        boolean lock = true;
        FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);

        // This time we write to the channel directly
        writeChannel.write(ByteBuffer.wrap
            (imageData.getBytes()));

        // Now finalize
        writeChannel.closeFinally();
        return fileService.getBlobKey(file);
    }

有谁知道我如何调整官方示例以使用端点(在我必须使用我的应用引擎实例的情况下)或使用 getServingUrl(绕过我的实例)来存储和提供我的 blob?
请包含代码,而不是文字.谢谢.

Does anyone know how I can either adapt the official example to use endpoints (in the case where I must use my app-engine instances) or use getServingUrl (bypassing my instances) to store and serve my blobs?
Please, instead of words, include the code. Thanks.

推荐答案

我将分享我是如何做到这一点的.我没有使用 google-cloud-endpoints,而是我自己的基于 REST 的 api,但无论哪种方式都应该是相同的想法.

I'll share how I'm doing this. I'm not using the google-cloud-endpoints, but just my own rest based api, but it should be the same idea either way.

我会用代码一步一步地把它布置出来,希望它会很清楚.您只需调整发送请求以使用端点的方式,而不是像本示例中那样使用更通用的方式.我包括了一些样板文件,但为了简洁不包括 try/catch、错误检查等.

I'll lay it out step by step with code, hopefully it will be clear. You'd simply adapt the way you send your requests to use endpoints instead of doing it more generic like in this example. I'm including some boilerplate, but excluding try/catch,error checking etc for brevity.

第 1 步(客户)

第一个客户端从服务器请求上传网址:

First client requests an upload url from server:

HttpClient httpclient = new DefaultHttpClient();    
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000); //Timeout Limit

HttpGet httpGet = new HttpGet("http://example.com/blob/getuploadurl");
response = httpclient.execute(httpGet);

第 2 步(服务器)

在服务器端,上传请求 servlet 看起来像这样:

On the server side the upload request servlet would look something like this:

String blobUploadUrl = blobstoreService.createUploadUrl("/blob/upload");

res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("text/plain");

PrintWriter out = res.getWriter();
out.print(blobUploadUrl);
out.flush();
out.close();

注意 createUploadUrl 的参数.这是客户所在的地方实际上传完成后重定向.那就是您将处理存储 blobkey 和/或服务 url 并将其返回给客户端.您必须将 servlet 映射到该 url,它将处理步骤 4

第 3 步(客户)再次返回客户端,使用步骤 2 返回的 url 将实际文件发送到上传 url.

Step 3 (client) Back to the client again to send the actual file to the upload url using the url returned from step 2.

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uploadUrlReturnedFromStep2);

FileBody fileBody  = new FileBody(thumbnailFile);
MultipartEntity reqEntity = new MultipartEntity();

reqEntity.addPart("file", fileBody);

httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost)

在步骤 2 中将此请求发送到 servlet 后,它将被重定向到您之前在 createUploadUrl() 中指定的 servlet

Once this request is sent to the servlet in step 2, it will be redirected to the servlet you specified in the createUploadUrl() earlier

第 4 步(服务器)

回到服务器端:这是处理映射到 blob/upload 的 url 的 servlet.我们将在这里将 blobkey 和服务 url 在 json 对象中返回给客户端:

Back to the server side: This is the servlet handling the url mapped to blob/upload. We will here return the blobkey and serving url to the client in a json object:

List<BlobKey> blobs = blobstoreService.getUploads(req).get("file");
BlobKey blobKey = blobs.get(0);

ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey);

String servingUrl = imagesService.getServingUrl(servingOptions);

res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("application/json");

JSONObject json = new JSONObject();
json.put("servingUrl", servingUrl);
json.put("blobKey", blobKey.getKeyString());

PrintWriter out = res.getWriter();
out.print(json.toString());
out.flush();
out.close();

第 5 步(客户)

我们将从 json 中获取 blobkey 和服务 url,然后将其与用户 ID 等一起发送以存储在数据存储实体中.

We'll get the blobkey and serving url from the json and then send it along with user id etc to store in the datastore entity.

JSONObject resultJson = new JSONObject(resultJsonString);

String blobKey = resultJson.getString("blobKey");
String servingUrl = resultJson.getString("servingUrl");

List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

nameValuePairs.add(new BasicNameValuePair("userId", userId));
nameValuePairs.add(new BasicNameValuePair("blobKey",blobKey));
nameValuePairs.add(new BasicNameValuePair("servingUrl",servingUrl));

HttpClient httpclient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000);

HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);

// Continue to store the (immediately available) serving url in local storage f.ex

第 6 步(服务器)实际上将所有内容存储在数据存储中(在本例中使用 objectify)

Step 6 (server) Actually storing everything in the datastore (using objectify in this example)

final String userId   = req.getParameter("userId");
final String blobKey  = req.getParameter("blobKey");
final String servingUrl = req.getParameter("servingUrl");

ExampleEntity entity = new ExampleEntity();
entity.setUserId(userId);
entity.setBlobKey(blobKey);
entity.setServingUrl(servingUrl);

ofy().save().entity(entity);

我希望这能让事情变得更清楚.如果有人想编辑答案以使用云端点而不是这个更通用的例子,请随意:)

I hope this makes things more clear. If someone wants to edit the answer to use cloud endpoints instead of this more generic example, feel free :)

关于服务网址

服务 url 是一种向客户提供图像的好方法,因为它可以动态地动态缩放图像.例如,您可以通过在服务 url 的末尾附加 =sXXX 来向您的 LDPI 用户发送较小的图像.其中 XXX 是图像最大尺寸的像素大小.你完全避开你的实例,只为带宽付费,用户只下载她需要的东西.

The serving url is a great way to serve images to your clients, because of the way it can dynamically scale images on the fly. For example you can send smaller images to your LDPI users by simply appending =sXXX at the end of the serving url. Where XXX is the pixel size of the largest dimension of your image. You completely avoid your instances and only pay for bandwidth, and the user only downloads what she needs.

附注!

应该可以在第 4 步停止并直接将它存储在那里,通过在第 3 步传递 userId f.ex.任何参数都应该被发送到第 4 步,但我没有让它工作,所以这就是我目前的做法,所以我以这种方式分享它,因为我知道它有效.

It should be possible to stop at step 4 and just store it directly there, by passing along userId f.ex in step 3. Any parameters are supposed to be sent along to Step 4, but I did not get that to work, so this is how I do it at the moment, so I'm sharing it this way since i know it works.

这篇关于将 blobstore 与谷歌云端点和 android 一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆